【问题标题】:Reshape data long data in R or aggregate?重塑数据 R 中的长数据还是聚合?
【发布时间】:2014-12-17 15:02:12
【问题描述】:

我有一个长格式的数据集,但我似乎无法将其用于分析。也许这个形状是合适的——我的经验几乎完全是宽格式数据,所以这个数据文件对我来说没有意义。 (可复制的数据文件在帖子末尾。)

> head(df,10)
    ID attributes values
1   1         AU    AAA
2   1         AU    BBB
3   1         YR   2014
4   2         AU    CCC
5   2         AU    DDD
6   2         AU    EEE
7   2         AU    FFF
8   2         AU    GGG
9   2         YR   2013
10  3         AU    HHH

属性列包含我感兴趣的变量,我想执行一系列聚合函数。例如,我想:

1.获取每个 ID 的作者数 (AU)。例如:

   ID       N.AU
    1           2
    2           5
    3           1
    4           2
    5           5
    6           1
  1. 按年份 (YR) 计算作者的中位数 (AU)

    YR           Median.N.AU   
    2013          5.0
    2014          1.5
    

对于这两个示例,我已经尝试使用 group_by 和 summaries 进行 dplry,但还没有破解代码。我也试过dcast。我希望提出一个解决方案,我可以轻松地将其推广到更大的数据框,该数据框具有更多的属性,可以采用单个值或多个值。任何帮助或指向类似解决方案的指针将不胜感激。

attributes = c("AU", "AU", "YR", "AU", "AU", "AU", "AU", "AU", "YR", "AU", "YR",
   "AU", "AU", "YR", "AU", "AU", "AU", "AU", "AU", "YR", "AU", "YR")
ID = c(1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6)
values = c("AAA", "BBB", "2014", "CCC", "DDD", "EEE", "FFF", "GGG", "2013", "HHH", "2014",
   "III", "JJJ", "2014", "KKK", "LLL", "MMM", "NNN", "OOO", "2013", "PPP", "2014")
df <- data.frame(ID, attributes, values)

【问题讨论】:

  • (1) 的基本解决方案可能类似于aggregate(attributes ~ ID, data = df[df$attributes == "AU", ], FUN = length),dplyr 版本可能类似于df %&gt;% filter(attributes == "AU") %&gt;% group_by(ID) %&gt;% summarise(N.AU = length(attributes))YR 列似乎不见了 (?)。
  • @lukeA 我几乎在 dplyr 版本中获得了正确的代码,非常感谢! YR 是我正在努力解决的问题。那是在数据文件中作为列中的变量,这就是给我带来问题的原因!
  • 不知道为什么这个问题得到了几票反对?
  • 这就是我想知道的!我会尝试通过反馈来改进我的问题......到目前为止,我收到的帮助对我的特殊需求非常有帮助。
  • 我认为你的中位数计算是错误的

标签: r reshape dplyr


【解决方案1】:

我认为您会感到困惑,因为您实际上有两张表 由通用 ID 链接的数据:

library(dplyr)
df <- tbl_df(df)

years <- df %>% 
  filter(attributes == "YR") %>% 
  select(id = ID, year = values)
years
#> Source: local data frame [6 x 2]
#> 
#>    id year
#> 1   1 2014
#> 2   2 2013
#> 3   3 2014
#> 4   4 2014
#> 5   5 2013
#> .. ..  ...

authors <- df %>% 
  filter(attributes == "AU") %>% 
  select(id = ID, author = values)
authors
#> Source: local data frame [16 x 2]
#> 
#>    id author
#> 1   1    AAA
#> 2   1    BBB
#> 3   2    CCC
#> 4   2    DDD
#> 5   2    EEE
#> .. ..    ...

获得此表格中的数据后,回答问题就很容易了 你有兴趣:

  1. 每篇论文的作者:

    n_authors <- authors %>% 
      group_by(id) %>% 
      summarise(n = n())
    

    或者

    n_authors <- authors %>% count(id)
    
  2. 每年作者的中位数:

    n_authors %>%
      left_join(years) %>%
      group_by(year) %>%
      summarise(median(n))
    #> Joining by: "id"
    #> Source: local data frame [2 x 2]
    #> 
    #>   year median(n)
    #> 1 2013       5.0
    #> 2 2014       1.5
    

【讨论】:

  • @docendodiscimus 是的,刚刚添加了一个示例
  • 是的,有共同ID的两张表更能说明我的困惑。如果这样会更好,我肯定会编辑帖子的标题。非常感谢!
【解决方案2】:

这是一个可能的data.table 解决方案

我还建议创建一些带有分隔列的聚合数据集。例如:

library(data.table)
(subdf <- as.data.table(df)[, .(N.AU = sum(attributes == "AU"),
                                Year = values[attributes == "YR"]) , ID])
#    ID N.AU Year
# 1:  1    2 2014
# 2:  2    5 2013
# 3:  3    1 2014
# 4:  4    2 2014
# 5:  5    5 2013
# 6:  6    1 2014

每年计算中位数

subdf[, .(Median.N.AU = median(N.AU)), keyby = Year]
#    Year Median.N.AU
# 1: 2013         5.0
# 2: 2014         1.5

【讨论】:

    【解决方案3】:

    我最初误解了您的数据集的结构。感谢下面的 cmets,我意识到您的数据需要重组。

    # split the data out
    df1 <- df[df$attributes == "AU",]
    df2 <- df[df$attributes == "YR",]
    
    # just keeping the columns with data as opposed to the label
    df3 <- merge(df1, df2, by="ID")[,c(1,3,5)]
    # set column names for clarification
    colnames(df3) <- c("ID","author","year")
    
    # get author counts
    num.authors <- count(df3, vars=c("ID","year"))
      ID year freq
    1  1 2014    2
    2  2 2013    5
    3  3 2014    1
    4  4 2014    2
    5  5 2013    5
    6  6 2014    1
    
    summaryBy(freq ~ year, data = num.authors, FUN = list(median))
      year freq.median
    1 2013         5.0
    2 2014         1.5
    

    summaryBy 的好处在于您可以添加列表中已定义的函数,您将获得包含其他指标(例如均值、标准差等)的另一列

    【讨论】:

    • 在这两个例子中都避免使用which。它有效,但不是必需的,也不是 Rish。
    • @DieterMenne,删除 which 确实有效,但不提供 OP 显示的过滤输出。有没有你推荐的替代品?
    • 当我使用count(df[df$attributes == "AU",], vars=c("ID", "attributes")) 时,我看不出有什么不同。我错过了什么吗?
    • @DieterMenne,啊!,我误会了,我以为你是说要删除过滤器。您确实是正确的,不需要which。谢谢
    • @DavidArenburg,谢谢,我尴尬地忽略了数据集的结构。我已经相应地编辑了我的答案。
    猜你喜欢
    • 1970-01-01
    • 2019-01-07
    • 2015-02-03
    • 2015-10-14
    • 2016-06-27
    • 1970-01-01
    • 1970-01-01
    • 2014-10-10
    • 1970-01-01
    相关资源
    最近更新 更多