【问题标题】:Adding aggregated counts as extra dataframe rows添加聚合计数作为额外的数据框行
【发布时间】:2015-07-04 18:19:06
【问题描述】:

我有一个包含英文字母及其频率的数据框。现在,如果还知道元音和辅音的频率以及出现的总数,那就太好了 - 因为我想绘制所有这些信息,所以我需要将它放在一个数据框中。

所以我经常发现自己处于这样的境地:

df <- data.frame(letter = letters, freq = sample(1:100, length(letters)))

df_vowels <- data.frame(letter = "vowels", freq = sum(df[df$letter %in% c("a", "e", "i", "o", "u"), ]$freq))
df_consonants <- data.frame(letter = "consonants", freq = sum(df[!df$letter %in% c("a", "e", "i", "o", "u"), ]$freq))
df_totals <- data.frame(letter = "totals", freq = sum(df$freq))

df <- rbind(df, df_vowels, df_consonants, df_totals)

我这样做是对的还是有更优雅的解决方案?

看来我的描述非常混乱:

基本上,我想向数据框中添加新类别(行)。在这个非常简单的示例中,它只是汇总数据。

(对于时间序列图,我使用聚合函数。)

【问题讨论】:

  • 在您的示例数据集中,每个字母只有一个元素。那么,为什么需要聚合
  • 对不起,我弄错了。我会立即解决这个问题。
  • 您的示例中每个字母仍然只有一行。您可以查看我帖子中的示例。
  • 您显示的预期结果可能不是情节所必需的。如果您提供了有关情节的更多信息,可能会有所帮助。
  • 请看我的更新。

标签: r dataframe aggregate rbind split-apply-combine


【解决方案1】:

编辑:这是您问题第三版的一个非常优雅的答案:

df <- data.frame(letter = letters, freq = sample(1:100, length(letters)),
                 stringsAsFactors=F)

df = df %>% group_by(letter) %>% summarize(freq = sum(freq))

df.tots = df %>% group_by(is_vowel = letter %in% c('a','e','i','o','u')) %>%
                 summarize(freq=sum(freq))

# Now we just rbind your three summary rows onto the df, then pipe it into your ggplot  
df %>%
  rbind(c('vowels',     df.tots[df.tots$is_vowel==T,]$freq)) %>%
  rbind(c('consonants', df.tots[df.tots$is_vowel==F,]$freq)) %>%
  rbind(c('total',      sum(df.tots$freq)))                  %>%
  ggplot( ... your_ggplot_command_goes_here ...)

  #qplot(data=..., x=letter, y=freq, stat='identity', geom='histogram')
  # To keep your x-axis in order, i.e. our summary rows at bottom,
  # you have to explicitly set order of factor levels:
  # df$letter = factor(df$letter, levels=df$letter)

注意事项:

  1. 我们需要data.frame(... stringsAsFactors=F),所以我们以后可以追加 'vowels', 'consonants', 'total' 行因为这些不会出现 在“字母”的因子水平中
  2. 请注意,dplyr group_by(is_vowel = ...) 允许我们同时插入一个新列 (mutate),然后在该表达式 (group_by) 上拆分,所有这些都在一个紧凑的行中。整洁的。从来不知道可以做到这一点。
  3. 你应该可以让bind_rows 工作到最后,但我做不到。

编辑:第二个版本。你说你想做一个聚合,所以我们认为每个字母在 df 中都有 >1 条记录。您似乎只是将 df 拆分为元音和辅音,然后再次合并,所以我认为除了is_vowel 之外不需要新的列。一种方法是使用 dplyr:

require(dplyr)
#  I don't see why you don't just overwrite df here with df2, the df of totals...
df2 = df %>% group_by(letter) %>% summarize(freq = sum(freq))
   letter     freq
1       a      150
2       b       33
3       c       54
4       d      258
5       e      285
6       f      300
7       g      198
8       h       27
9       i       36
10      j      189
..    ...      ...

# Now add a logical column, so we can split on it when aggregating
# df or df2 ....
df$is_vowel = df$letter %in% c('a','e','i','o','u')

# Then your total vowels are:
df %>% filter(is_vowel==T) %>% summarize(freq = sum(freq))
     freq
      312
# ... and total consonants ...
df %>% filter(is_vowel==F) %>% summarize(freq = sum(freq))
     freq
     1011

这是另一种方式,如果您想避免 dplyr,则使用单线:

split(df, df$letter %in% c("a", "e", "i", "o", "u") )

顺便说一句,你可以通过从所有字母中减去元音来更容易地形成辅音列表(/集合):

setdiff(letters, c("a", "e", "i", "o", "u"))
# "b" "c" "d" "f" "g" "h" "j" "k" "l" "m" "n" "p" "q" "r" "s" "t" "v" "w" "x" "y" "z"

【讨论】:

  • 无论如何这给了你一个想法,如果你的意思不同,请更新你的例子。
  • 我想我的意思是不同的。请查看我的更新。
  • 第三次更新。不再为您做任何事情:) 动态创建一个对象,然后使用 dplyr 的%&gt;% 管道进入 ggplot 非常优雅。你可以围绕这个包装一个函数。
  • 我认为你已经获得了讽刺的权利。 :-) 说真的,非常感谢!!我不知道 R 中的管道。
  • 可悲的是,管道被搞砸了,需要在行级别上设置顺序df$letter = factor(df$letter, levels=df$letter)
【解决方案2】:

你可以试试

 v2 <- with(df, tapply(freq, c('consonants', 'vowels')[letter %in% 
              v1+1L], FUN=sum))

 df1 <- rbind(df, data.frame(letter=c(names(v2),"Total"), 
            freq=c(v2, sum(v2)), stringsAsFactors=FALSE))
 library(ggplot2)
 ggplot(df1, aes(x=letter, y=freq)) +
                  geom_bar(stat='identity')

数据

set.seed(24)
df <- data.frame(letter= sample(letters,200, replace=TRUE),
 freq = sample(1:100, 200, replace=TRUE), stringsAsFactors=FALSE)
v1 <- c("a", "e", "i", "o", "u")

【讨论】:

  • 仅供参考 dcast 需要 1.9.5,这是开发版本; CRAN 目前只有 1.9.4 可用
  • @smci 安装devel版本的说明是here
  • 是的,只是让人们知道,否则他们会看到Error: object 'dcast' not found
  • @smci 感谢您的评论。是的,我在帖子中添加了该信息
猜你喜欢
  • 2020-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-05
  • 1970-01-01
  • 1970-01-01
  • 2020-05-18
  • 2022-07-22
相关资源
最近更新 更多