我有一个超过130 000行的data.table。
我想通过变量dates
对两个cols progress
和id
进行分组,然后将值放在向量中,以便我使用aggregate()
。
df_agr <- aggregate(cbind(progress, dates) ~ id, data = df_test, FUN = c)
然而,聚合数据大约需要52秒+我从col dates
中丢失了日期格式。
数据框的一个例子:
id dates progress
1: 3505H6856 2003-07-10 yes
2: 3505H6856 2003-08-21 yes
3: 3505H6856 2003-09-04 yes
4: 3505H6856 2003-10-16 yes
5: 3505H67158 2003-01-14 yes
6: 3505H67158 2003-02-18 yes
7: 3505H67862 2003-03-06 yes
8: 3505H62168 2003-04-24 no
9: 3505H62168 2003-05-15 yes
10: 3505H65277 2003-02-11 yes
我得到的结果:
id progress dates
1 3505H62168 1, 2 5, 6
2 3505H65277 2 2
3 3505H67158 2, 2 1, 3
4 3505H67862 2 4
5 3505H6856 2, 2, 2, 2 7, 8, 9, 10
我很惊讶地看到所有内容都转换为integer
+每行似乎包含“独立”向量,实际上是列表中的向量:
'data.frame': 5 obs. of 3 variables:
$ id : chr "3505H62168" "3505H65277" "3505H67158" "3505H67862" ...
$ progress:List of 5
..$ 1: int 1 2
..$ 2: int 2
..$ 3: int 2 2
..$ 4: int 2
..$ 5: int 2 2 2 2
$ dates :List of 5
..$ 1: int 5 6
..$ 2: int 2
..$ 3: int 1 3
..$ 4: int 4
..$ 5: int 7 8 9 10
我尝试使用以下格式转换回正确格式的日期:
lapply(df_agr$dates, function(x) as.Date(x, origin="1970-01-01"))
但我得到了:
$`1`
[1] "1970-01-06" "1970-01-07"
$`2`
[1] "1970-01-03"
$`3`
[1] "1970-01-02" "1970-01-04"
$`4`
[1] "1970-01-05"
$`5`
[1] "1970-01-08" "1970-01-09" "1970-01-10" "1970-01-11"
所以看来起源不是"1970-01-01"
,因为它是在文档中写的,也许是数据中最低的日期?
所以我的问题是:如何在保留日期格式的同时使aggregate()
与data.table
获得相同的结果?
因此,它意味着如何使用data.table按唯一ID进行分组。我试过了:
setDT(df)[,list(col1 = c(progress), col2 = c(dates)), by = .(unique(id))]
但当然我得到了跟随错误:
[.data.table
中的错误(df ,, list(col1 = c(进度),col2 = c(日期)),:'by'或'keyby'列表中的项目是length(5)。 每个必须与x中的行或i返回的行数相同 (10)。
数据:
structure(list(id = c("3505H6856", "3505H6856", "3505H6856",
"3505H6856", "3505H67158", "3505H67158", "3505H67862", "3505H62168",
"3505H62168", "3505H65277"), dates = structure(c(12243, 12285,
12299, 12341, 12066, 12101, 12117, 12166, 12187, 12094), class = "Date"),
progress = c("yes", "yes", "yes", "yes", "yes", "yes", "yes",
"no", "yes", "yes")), .Names = c("id", "dates", "progress"
), class = c("data.frame"), row.names = c(NA, -10L
))
答案 0 :(得分:2)
您可以使用paste0
我认为如下所示,您需要将日期更改为字符,以便它不会转换为其数字对应项,在查询下方运行而不将日期转换为数字将为您提供值比如,12166,12187。在你的查询中,你也在使用&#34; c&#34;至于组合对象,但是我们应该使用paste来组合,当你使用时也会在data.table中使用。(id)in by它应该为你提供唯一的值,除非你的查询有一些东西没有让事物变得独特在这种情况下,如果您避免崩溃声明,您将无法获得ID上的唯一键,我希望这是有帮助的。感谢:
df_agr <- aggregate(cbind(progress, as.character(dates)) ~ id, data = df, FUN = paste0)
> df_agr
id progress V2
1 3505H62168 no, yes 2003-04-24, 2003-05-15
2 3505H65277 yes 2003-02-11
3 3505H67158 yes, yes 2003-01-14, 2003-02-18
4 3505H67862 yes 2003-03-06
5 3505H6856 yes, yes, yes, yes 2003-07-10, 2003-08-21, 2003-09-04, 2003-10-16
>
使用data.table:
setDT(df)[,.(paste0(progress,collapse=","), paste0(as.character(dates),collapse=",")), by = .(id)]
id V1 V2
1: 3505H6856 yes,yes,yes,yes 2003-07-10,2003-08-21,2003-09-04,2003-10-16
2: 3505H67158 yes,yes 2003-01-14,2003-02-18
3: 3505H67862 yes 2003-03-06
4: 3505H62168 no,yes 2003-04-24,2003-05-15
5: 3505H65277 yes 2003-02-11
或者只是大卫·阿伦伯格指出的,更简单的数据方式。表示感谢您的宝贵意见:
setDT(df)[, lapply(.SD, toString), by = id]
答案 1 :(得分:0)
dplyr版本。
library(dplyr)
df %>%
group_by(id) %>%
summarize (progress = paste(progress, collapse=","),
dates = paste(dates, collapse=",") )
# id progress dates
# <chr> <chr> <chr>
# 1 3505H62168 no,yes 2003-04-24,2003-05-15
# 2 3505H65277 yes 2003-02-11
# 3 3505H67158 yes,yes 2003-01-14,2003-02-18
# 4 3505H67862 yes 2003-03-06
# 5 3505H6856 yes,yes,yes,yes 2003-07-10,2003-08-21,2003-09-04,2003-10-16