【问题标题】:Spread unique values (in multiple columns) to different columns and paste aggregated values将唯一值(在多列中)传播到不同的列并粘贴聚合值
【发布时间】:2020-03-12 09:15:24
【问题描述】:

我有一个如下的数据框:

structure(list(Value = c(1, 2, 3, 4), col1 = structure(c(1L, 
1L, 2L, 2L), .Label = c("A1", "A2"), class = "factor"), col2 = structure(c(1L, 
2L, 2L, 1L), .Label = c("B1", "B2"), class = "factor"), col3 = structure(1:4, .Label = c("C1", 
"C2", "C3", "C4"), class = "factor")), class = "data.frame", row.names = c(NA, 
-4L))

我想使用 data.table 将每列中的唯一值传播到不同的列,并在每列下粘贴总和值(来自“值”列) 例如:列 col1 有 2 个唯一值 A1 和 A2。 A1 之和为 3,A2 为 7 同样,列 col2 有 2 个唯一值 B1 和 B2。 B1之和为5,B2之和为5

此操作将针对 col1、col2 和 col3 中的每一列执行。

预期输出如下

structure(list(A1 = 3, A2 = 7, B1 = 5, B2 = 5, C1 = 1, C2 = 2, 
    C3 = 3, C4 = 4), class = "data.frame", row.names = c(NA, 
-1L))

如何在 R 中实现这一点?

【问题讨论】:

标签: r dataframe data.table


【解决方案1】:

data.table@Sotos 的答案是:

library(data.table)

dcast(melt(setDT(df), 'Value')[, .(Total = sum(Value)), value],
           rowid(value)~value, value.var = 'Total')

#   value A1 A2 B1 B2 C1 C2 C3 C4
#1:     1  3  7  5  5  1  2  3  4

您可能不需要 value 列,因此您可以通过添加 [, value := NULL][] 来删除它

【讨论】:

  • heh...我刚刚在DT中完成了但比这更麻烦所以我不会费心添加
  • 也许还有一个更简洁的版本:P 但我也使用更多的 tidyverse 而不是 data.table
  • 我认为他们将dcast/melt 合二为一,但我可能会将其与reshape2 混淆...不确定
  • fun.aggregate 中有 fun.aggregate 参数,但我猜它不能按组求和。
【解决方案2】:

我不太适应data.table,但tidyverse 的解决方案可以,

library(dplyr)
library(tidyr)

df %>% 
 pivot_longer(starts_with('col')) %>% 
 group_by(value) %>% 
 summarise(res = sum(Value)) %>% 
 pivot_wider(names_from = value, values_from = res)

给出,

# A tibble: 1 x 8
     A1    A2    B1    B2    C1    C2    C3    C4
  <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1     3     7     5     5     1     2     3     4

【讨论】:

    【解决方案3】:

    Base R 版本(另一个 data.table 想要的):

    t(unstack(
        with(reshape(df, direction="long", 
                 varying=grep("^col", names(df), value=TRUE), sep=""),
         aggregate(formula=Value~col, FUN=sum)), 
      form=Value~col))
    

        A1 A2 B1 B2 C1 C2 C3 C4
    res  3  7  5  5  1  2  3  4
    

    【讨论】:

      【解决方案4】:

      这是另一种基本的 R 解决方案

      dfout <- t(do.call(rbind,
                         lapply(seq_along(df)[-1], 
                                function(k) unstack(rev(aggregate(Value~.,df[c(1,k)],sum))))))
      

      这样

      > dfout
          A1 A2 B1 B2 C1 C2 C3 C4
      res  3  7  5  5  1  2  3  4
      

      数据

      df <- structure(list(Value = c(1, 2, 3, 4), col1 = structure(c(1L, 
      1L, 2L, 2L), .Label = c("A1", "A2"), class = "factor"), col2 = structure(c(1L, 
      2L, 2L, 1L), .Label = c("B1", "B2"), class = "factor"), col3 = structure(1:4, .Label = c("C1", 
      "C2", "C3", "C4"), class = "factor")), class = "data.frame", row.names = c(NA, 
      -4L))
      

      【讨论】:

      • 我喜欢这个解决方案,但是如果有第 4 列 col4,或者通常更多列怎么办?你会如何修改这个?
      • @Edward 好问题!那么对于一般情况,您可以使用seq_along(df)[-1] 而不是2:4。查看我的更新
      【解决方案5】:

      这是另一种选择:

      library(data.table)
      x <- rbindlist(lapply(paste0("col", 1:3), function(b) df[, sum(Value), b]), 
          use.names=FALSE)
      
      setDT(setNames(as.list(x$V1), x$col1))[]
      

      数据:

      df <- structure(list(Value = c(1, 2, 3, 4), col1 = structure(c(1L, 
      1L, 2L, 2L), .Label = c("A1", "A2"), class = "factor"), col2 = structure(c(1L, 
      2L, 2L, 1L), .Label = c("B1", "B2"), class = "factor"), col3 = structure(1:4, .Label = c("C1", 
      "C2", "C3", "C4"), class = "factor")), class = "data.frame", row.names = c(NA, 
      -4L))
      

      【讨论】:

        【解决方案6】:

        你也可以这样解决:

        library(data.table)
        melt(setDT(df), "Value")[, .(TOT = sum(Value)), value][, setNames(as.list(TOT), value)]
        
        #       A1    A2    B1    B2    C1    C2    C3    C4
        # 1:     3     7     5     5     1     2     3     4
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-06-07
          • 1970-01-01
          • 2019-10-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-10-08
          相关资源
          最近更新 更多