基于变量中前N个最频繁值的子集 Dataframe

xsuvu9jc  于 2023-01-03  发布在  其他
关注(0)|答案(3)|浏览(117)

我的目标是创建一个长数据框的简单密度或条形图,显示课程(MOOC)中国籍的相对频率。我只是不希望所有的国籍都在那里,只是前10名。我创建了下面的示例df+我用于绘图的ggplot 2代码。

d=data.frame(course=sample(LETTERS[1:5], 500,replace=T),nationality=as.factor(sample(1:172,500,replace=T)))
mm <- ggplot(d, aes(x=nationality, colour=factor(course)))
mm + geom_bar() + theme_classic()

......但正如所说:我想要一个基于频率的整个数据集的子集。上面显示了所有数据。
PS.我添加ggplot 2代码是为了上下文,但也是因为ggplot 2本身可能有一些东西使这成为可能(不过我对此表示怀疑)。

**EDIT 2014-12-11:**目前的答案都是用ddplyr或者table的方法来达到想要的子集,但是我想知道是不是有更直接的方法来达到同样的效果。。我就先让它先留着吧,看看有没有其他的方法。

u59ebvdq

u59ebvdq1#

使用dplyr函数counttop_n获取前10个国籍。由于top_n考虑了平局,因此本例中包含的国籍数由于平局而超过10个。arrange计数,使用factorlevels按降序设置国籍。

# top-10 nationalities
d2 <- d %>%
  count(nationality) %>%
  top_n(10) %>%
  arrange(n, nationality) %>%
  mutate(nationality = factor(nationality, levels = unique(nationality)))

d %>%
  filter(nationality %in% d2$nationality) %>%
  mutate(nationality = factor(nationality, levels = levels(d2$nationality))) %>%
  ggplot(aes(x = nationality, fill = course)) +
    geom_bar()

ccrfmcuu

ccrfmcuu2#

下面是选择前10个国家的方法。请注意,多个国家共享相同的频率。因此,选择前10个国家会导致忽略一些具有相同频率的国家。

# calculate frequencies
tab <- table(d$nationality)
# sort
tab_s <- sort(tab)
# extract 10 most frequent nationalities
top10 <- tail(names(tab_s), 10)
# subset of data frame
d_s <- subset(d, nationality %in% top10)
# order factor levels
d_s$nationality <- factor(d_s$nationality, levels = rev(top10))

# plot
ggplot(d_s, aes(x = nationality, fill = as.factor(course))) +
  geom_bar() + 
  theme_classic()

请注意,我将colour更改为fill,因为colour会影响边框的颜色。

n3h0vuf2

n3h0vuf23#

虽然这些问题在一段时间前已经提出,但为了完整起见,我提出另外两个解决方案:

d_raw <- data.frame(
  course = sample(LETTERS[1:5], 500, replace = T),
  nationality = as.factor(sample(1:172, 500, replace=T))
)

1.一个使用forcats包中的fct_lump_n(),另一个使用filter()

d1 <- d_raw %>% 
   mutate(nationality = fct_lump_n(
     f = nationality, 
     n = 10,
     ties.method = "first"
   )) %>% 
   filter(nationality != "Other")

 d1 %>% count(nationality, sort = TRUE)

 ggplot(d1, aes(x = nationality, fill = course)) + # factor() is not needed here.
   geom_bar() + 
   theme_classic()

fct_lump_n()汇总了除10个最常见的国籍之外的所有国籍,并将其归入“其他”类别。请注意,在fct_lump_n()参数中,需要使用ties.method = "first"才能真正获取前10个国籍,而不是11或12个。所有其他国籍都标记为“其他”,即使它们可能与前10个国籍一样频繁出现。
国籍级别仅按字母顺序排列。

1.另一个解决方案是使用forcats包中的fct_infreq()cur_group_id()filter()

d2 <- d_raw %>% 
   group_by(nationality = fct_infreq(nationality)) %>% 
   filter(cur_group_id() <= 10) %>% 
   ungroup()

 d2 %>% count(nationality, sort = TRUE)

 ggplot(d2, aes(x = nationality, fill = course)) + # factor() is not needed here.
   geom_bar() + 
   theme_classic()

cur_group_id()为每个国籍分配一个组ID。为了从最常用的国籍开始,我们首先需要按频率对列nationality进行排序。然后,我们过滤前10个组ID,也就是最常用的10个国籍。
国籍级别首先按n排序,然后按字母顺序排序。

我使用count()来验证两个 Dataframe d1d2看起来是一样的。两种解决方案都有优点,即我们不需要第二个(临时) Dataframe 或临时向量。
我希望这对以后的人有帮助。

相关问题