R等价的Excel" Sumif(s)"像列一样的功能

时间:2017-07-12 00:49:33

标签: r database data.table aggregate

我对R(这个网站的新用户)相当新,并尝试了解如何在有超过1个标识符的情况下跨列聚合数据(在这种情况下,两个:PERSON_ID和PRODUCT_ID)。 / p>

请参阅下面的示例。在我的数据框中的两个标识符的右侧是包含每周销售数字的五列。我需要汇总每周数据,以便:

1:对具有相同名称的周列进行求和(通常这是我可以使用sumif / sumifs函数在MS Excel中轻松完成的事情)

2:任何包含相同PERSON_ID和PRODUCT_ID组合的行也会相加。

在这种特殊情况下,请注意,2017年2月2日这一周出现在多个列中。同时,对于相同的PRODUCT_ID,3024,PERSON_ID 0003603会出现两次。

PERSON_ID    PRODUCT_ID    6/23/2017   6/16/2017   6/9/2017   6/2/2017   6/2/2017
0003603      3024          10.000      5.000       4.000      3.000      2.000
0003603      3024          1.000       2.000       3.000      8.000      1.000     
0007654      2111          8.000       3.000       2.000      1.000      0.000
0008885      3025          0.000       0.000       1.000      3.000      9.000
0950645      3024          6.000       5.000       4.000      3.000      2.000

我的实际数据框包含超过100万条记录,因此,据我所知,使用data.table包的方法是理想的。

有人可以说明如何在R中解决这个特殊问题吗?

2 个答案:

答案 0 :(得分:2)

melt你的数据(重塑长)是要走的路。如果我理解了你正确的事情,那就简单地说:

x = fread('PERSON_ID    PRODUCT_ID  6/23/2017   6/16/2017   6/9/2017    6/2/2017    6/2/2017
0003603 3024    10.000  5.000   4.000   3.000   2.000
0003603 3024    1.000   2.000   3.000   8.000   1.000
0007654 2111    8.000   3.000   2.000   1.000   0.000
0008885 3025    0.000   0.000   1.000   3.000   9.000
0950645 3024    6.000   5.000   4.000   3.000   2.000',
          colClasses = c('character', 'character', rep('numeric', 5L)))

xmlt = 
  melt(x, id.vars = c('PERSON_ID', 'PRODUCT_ID'),
       variable.name = 'week', value.name = 'sales')

xmlt[ , week := as.IDate(week, format = '%m/%d/%Y')]

xmlt[ , .(total_sales = sum(sales)), 
      keyby = .(PERSON_ID, PRODUCT_ID, week)]
    PERSON_ID PRODUCT_ID       week total_sales
#  1:   0003603       3024 2017-06-02          14
#  2:   0003603       3024 2017-06-09           7
#  3:   0003603       3024 2017-06-16           7
#  4:   0003603       3024 2017-06-23          11
#  5:   0007654       2111 2017-06-02           1
#  6:   0007654       2111 2017-06-09           2
#  7:   0007654       2111 2017-06-16           3
#  8:   0007654       2111 2017-06-23           8
#  9:   0008885       3025 2017-06-02          12
# 10:   0008885       3025 2017-06-09           1
# 11:   0008885       3025 2017-06-16           0
# 12:   0008885       3025 2017-06-23           0
# 13:   0950645       3024 2017-06-02           5
# 14:   0950645       3024 2017-06-09           4
# 15:   0950645       3024 2017-06-16           5
# 16:   0950645       3024 2017-06-23           6

答案 1 :(得分:0)

我们首先定义df如下。请注意,R中的列名不能以数字开头,也不能重复。 R通过在以列号开头的列名前面添加X并在列名末尾添加.1.2等来更正这些内容。< / p>

df <- read.table(text = "
                 PERSON_ID    PRODUCT_ID    6/23/2017   6/16/2017   6/9/2017   6/2/2017   6/2/2017
                 0003603      3024          10.000      5.000       4.000      3.000      2.000
                 0003603      3024          1.000       2.000       3.000      8.000      1.000     
                 0007654      2111          8.000       3.000       2.000      1.000      0.000
                 0008885      3025          0.000       0.000       1.000      3.000      9.000
                 0950645      3024          6.000       5.000       4.000      3.000      2.000",
                 header = TRUE, colClasses = rep(c("character", "numeric"), c(2,5)))

我们可以使用dplyr(数据操作),tidyr(整洁的数据)和lubridate(使用日期)包来解决问题。

library(dplyr)
library(tidyr)
library(lubridate)
library(rebus)
df %>%
  gather(DATE, SALES, -c(PERSON_ID, PRODUCT_ID)) %>%
  mutate(DATE = str_extract(DATE, pattern = repeated(DGT, 1, 2) %R% DOT %R%
                                            repeated(DGT, 1, 2) %R% DOT %R%
                                            repeated(DGT, 4, 4)),
         DATE = mdy(DATE)) %>%
  group_by(PERSON_ID, PRODUCT_ID, DATE) %>%
  summarise_at(vars(SALES), funs(sum)) %>%
  ungroup

代码以下列方式编写:

  1. 广df转换为长格式。这是为了确保数据框中的行是观察值,列是变量。
  2. 格式化DATE变量以删除前缀X和后缀.1,并将日期类(月 - 日 - 年)强制转换为变量。
  3. 将数据框分组为3个变量,即PERSON_IDPRODUCT_IDDATE
  4. 对每个组的SALES变量求和(在上一点中定义)
  5. 如果您想将其转换回宽幅广告,可以在最后添加另一行,即%>% spread(DATE, SALES)