【问题标题】:how to accumulate several column and do summation?如何累积几列并求和?
【发布时间】:2019-06-25 01:53:03
【问题描述】:

我想合并 15 列,它们有 3 个相同的列(所以它有 5 个相同的副本)。我的数据看起来像这样(例如,为了简单起见,它只有 3 个副本)

   date     sku1  prod1  tot1  sku2  prod2  tot2  sku3  prod3  tot3
01/02/2019  100     a    100
01/02/2019  100     a    200    101    b     50
02/02/2019  101     b    100
02/02/2019  101     b     50    102    c    100   100     a     50
02/02/2019  102     c     50

变成这样

   date     sku  all_prod  total
01/02/2019  100     a       300
01/02/2019  101     b        50
02/02/2019  101     b       150
02/02/2019  102     c       150
02/02/2019  100     a        50

有人知道怎么做吗?提前感谢这么多

【问题讨论】:

  • 请使用dput 显示示例。这些是空白 ("") 还是 NAs?
  • 不清楚条件。可能是library(data.table); melt(setDT(df1), measure = patterns("^sku", "^prod", "^tot"), na.rm = TRUE, value.name = c("sku", "all_prod", "total"))[, lapply(.SD, sum, na.rm = TRUE), .(date, all_prod), .SDcols = c("sku", "total")]
  • 那些空白不适用

标签: r addition


【解决方案1】:

使用dplyrtidyr我们可以将gather数据变成长格式,从列名中删除数字,spread它变成宽格式,group_bydateprod值和在每组中取sumtot 值。

library(dplyr)
library(tidyr)

df %>%
  gather(key, value, -date, na.rm = TRUE) %>%
  mutate(key = sub("(.*)\\d+", "\\1", key)) %>%
  group_by(key) %>%
  mutate(row = row_number()) %>%
  spread(key, value) %>%
  mutate_at(vars(sku, tot), as.numeric) %>%
  group_by(date, prod) %>%
  summarise(sku = sku[1L], 
            tot = sum(tot))

#  date       prod    sku   tot
#  <fct>      <chr> <dbl> <dbl>
#1 01/02/2019 a       100   300
#2 01/02/2019 b       101    50
#3 02/02/2019 a       100    50
#4 02/02/2019 b       101   150
#5 02/02/2019 c       102   150

数据

df <- structure(list(date = structure(c(1L, 1L, 2L, 2L, 2L), .Label = 
c("01/02/2019", "02/02/2019"), class = "factor"), sku1 = c(100, 100, 101, 101, 
102), prod1 = structure(c(1L, 1L, 2L, 2L, 3L), .Label = c("a", 
"b", "c"), class = "factor"), tot1 = c(100, 200, 100, 50, 50), 
sku2 = c(NA, 101, NA, 102, NA), prod2 = structure(c(NA, 1L, 
NA, 2L, NA), .Label = c("b", "c"), class = "factor"), tot2 = c(NA, 
50, NA, 100, NA), sku3 = c(NA, NA, NA, 100, NA), prod3 = 
structure(c(NA, NA, NA, 1L, NA), .Label = "a", class = "factor"), tot3 = c(NA, 
NA, NA, 50, NA)), row.names = c(NA, -5L), class = "data.frame")

【讨论】:

  • 什么-日期; na.rm 是什么意思?
  • 还有“mutate(key = sub("(.*)\\d+", "\\1", key))" 是什么意思?谢谢
  • @NicodemusSigitSutanto 使用gather,我们将数据转换为键/值对,其中键是列名,值是列中的值。通过指定-date,我们保持date 列不变。 na.rm 用于删除 NA 值。而sub 用于从sku1sku2prod1 和其他列名中删除数字部分。如果代码太混乱,如果您想更好地理解代码,我建议您逐行运行代码并查看输出。
  • 我在运行你的代码后得到一个这样的错误代码 -> “警告信息:强制引入的 NAs ”并且总数没有显示正确的添加结果
  • 如果我想在日期旁边添加另一个列名怎么办?所以我应该这样写“收集(键,值,(-date,-example),na.rm = TRUE)”?
【解决方案2】:

一个选项是 melt from data.table 可以采用多个 measure patterns

library(data.table)
melt(setDT(df1), measure = patterns("^prod", "^tot"), na.rm = TRUE, 
    value.name = c( "all_prod", "total"))[, c(list(sku = first(sku1)), 
    lapply(.SD, sum, na.rm = TRUE)), .(date, all_prod),
          .SDcols = c("total")][order(date)]
#        date all_prod sku total
#1: 01/02/2019        a 100   300
#2: 01/02/2019        b 100    50
#3: 02/02/2019        b 101   150
#4: 02/02/2019        c 102   150
#5: 02/02/2019        a 101    50

数据

df1 <- structure(list(date = structure(c(1L, 1L, 2L, 2L, 2L), .Label = 
 c("01/02/2019", "02/02/2019"), class = "factor"), sku1 = c(100, 100, 101, 101, 
 102), prod1 = structure(c(1L, 1L, 2L, 2L, 3L), .Label = c("a", 
 "b", "c"), class = "factor"), tot1 = c(100, 200, 100, 50, 50), 
 sku2 = c(NA, 101, NA, 102, NA), prod2 = structure(c(NA, 1L, 
 NA, 2L, NA), .Label = c("b", "c"), class = "factor"), tot2 = c(NA, 
 50, NA, 100, NA), sku3 = c(NA, NA, NA, 100, NA), prod3 = 
 structure(c(NA, NA, NA, 1L, NA), .Label = "a", class = "factor"), tot3 = c(NA, 
 NA, NA, 50, NA)), row.names = c(NA, -5L), class = "data.frame")

【讨论】:

  • 我收到类似这样的错误消息“此外:警告消息:1:在 melt.data.table(setDT(forwhx1), measure = patterns("^skuproduk", : 'measure.vars ' [skuproduk1, skuproduk2, skuproduk3, skuproduk4, skuproduk5] 不都是同一类型。按照层次顺序,熔融数据值列将是“字符”类型。所有非“字符”类型的度量变量都将被强制也。查看 ?melt.data.table 中的详细信息以了解有关强制的更多信息。”
  • 实际上数据并没有像示例中那样按顺序排列,所以我认为“c(list(sku=first(sku1))”在这里有问题
  • @NicodemusSigitSutanto 使用您提供的示例,我没有收到任何错误
  • "value.name = c("all_prod", "total"))[, c(list(sku = first(sku1))" 是什么意思?
  • @NicodemusSigitSutanto 默认情况下,如果您不提供该选项,则值列将以其默认名称命名,即。 'value1'、'value2'、'value3',要修改它,我们使用value.name。第二部分是根据分组变量获取'sku'的first元素
猜你喜欢
  • 1970-01-01
  • 2014-12-11
  • 2017-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-15
  • 2022-01-13
相关资源
最近更新 更多