我比较熟悉data.table
,而不是那么熟悉dplyr
.我已经阅读了一些出现在SO上的dplyr
小插曲和例子,到目前为止我的结论是:
data.table
并且dplyr
在速度上具有可比性,除非有许多(即> 10-100K)组,并且在某些其他情况下(参见下面的基准)dplyr
有更多可访问的语法dplyr
摘要(或将)潜在的DB交互在我看来2.没有多大的重量,因为我对它很熟悉data.table
,虽然我明白对于那些对这两者都不熟悉的用户来说这将是一个很重要的因素.我想避免争论哪个更直观,因为这与我从已经熟悉的人的角度提出的具体问题无关data.table
.我还想避免讨论"更直观"如何导致更快的分析(当然是真的,但同样,不是我最感兴趣的).
我想知道的是:
最近的一个问题让我更多地思考这个问题,因为直到那时我才认为dplyr
会提供超出我已经做过的东西data.table
.这是dplyr
解决方案(Q末尾的数据):
dat %.%
group_by(name, job) %.%
filter(job != "Boss" | year == min(year)) %.%
mutate(cumu_job2 = cumsum(job2))
Run Code Online (Sandbox Code Playgroud)
这比我的黑客尝试data.table
解决方案要好得多.也就是说,好的data.table
解决方案也相当不错(感谢Jean-Robert,Arun,并注意到这里我赞成对最严格的最佳解决方案的单一陈述):
setDT(dat)[,
.SD[job != "Boss" | year == min(year)][, cumjob := cumsum(job2)],
by=list(id, job)
]
Run Code Online (Sandbox Code Playgroud)
后者的语法可能看起来非常深奥,但如果你习惯了data.table
(即不使用一些更深奥的技巧),它实际上非常简单.
理想情况下,我希望看到的是一些很好的例子,dplyr …
我有一个data.table,大约有300万行和40列.我想按照以下sql模拟代码中的组内降序对此表进行排序:
sort by ascending Year, ascending MemberID, descending Month
Run Code Online (Sandbox Code Playgroud)
在data.table中是否有相同的方法来执行此操作?到目前为止,我必须将其分解为两个步骤:
setkey(X, Year, MemberID)
Run Code Online (Sandbox Code Playgroud)
这非常快,只需几秒钟.
X <- X[,.SD[order(-Month)],by=list(Year, MemberID)]
Run Code Online (Sandbox Code Playgroud)
这个步骤需要更长的时间(5分钟).
更新:有人发表评论X <- X[sort(Year, MemberID, -Month)]
并稍后删除.这种方法似乎要快得多:
user system elapsed
5.560 11.242 66.236
Run Code Online (Sandbox Code Playgroud)
我的方法:setkey()然后订购(-Month)
user system elapsed
816.144 9.648 848.798
Run Code Online (Sandbox Code Playgroud)
我现在的问题是:如果我想按年份,MemberId和sort(Year,MemberID,Month)之后的月份进行汇总,data.table是否会识别排序顺序?
更新2:回应Matthew Dowle:
在使用Year,MemberID和Month的setkey之后,每组仍然有多个记录.我想要的是总结每个小组.我的意思是:如果我使用X [order(Year,MemberID,Month)],求和是否利用data.table的二进制搜索功能:
monthly.X <- X[, lapply(.SD[], sum), by = list(Year, MemberID, Month)]
Run Code Online (Sandbox Code Playgroud)
更新3:Matthew D提出了几种方法.第一种方法的运行时间比order()方法快:
user system elapsed
7.910 7.750 53.916
Run Code Online (Sandbox Code Playgroud)
马修:让我感到惊讶的是大部分时间转换月份的标志.没有它,setkey的速度非常快.
我有两个data.table X和ÿ.
列X:area, id, value
在列ÿ:ID, price, sales
创建两个data.tables:
X = data.table(area=c('US', 'UK', 'EU'),
id=c('c001', 'c002', 'c003'),
value=c(100, 200, 300)
)
Y = data.table(ID=c('c001', 'c002', 'c003'),
price=c(500, 200, 400),
sales=c(20, 30, 15)
)
Run Code Online (Sandbox Code Playgroud)
我为X和Y设置了键:
setkey(X, id)
setkey(Y, ID)
Run Code Online (Sandbox Code Playgroud)
现在,我尝试加入X和Ÿ通过id
在X和ID
在ÿ:
merge(X, Y)
merge(X, Y, by=c('id', 'ID'))
merge(X, Y, by.x='id', by.y='ID')
Run Code Online (Sandbox Code Playgroud)
所有引发的错误都说明by
参数中的列名无效.
我参考了data.table手册,发现merge
函数不支持 …
如果我理解正确,默认情况下,data.table
通过比较设置为键并具有相同名称的列来合并两个表.如果我有不同列名的表,我该怎么写?例如:
set.seed(123)
DT1<-data.table(col1=sample(letters,5,replace=TRUE),col2=sample(LETTERS[1:5],5,replace=TRUE),col3=sample(1:2,5,replace=TRUE))
DT2<-data.table(col4=sample(1:3,10,replace=TRUE),col5=sample(LETTERS[1:5],10,replace=TRUE),col6=sample(1:100,10,replace=TRUE))
(DT1)
(DT2)
> (DT1)
col1 col2 col3
1: h A 2
2: u C 1
3: k E 2
4: w C 2
5: y C 1
> (DT2)
col4 col5 col6
1: 3 D 48
2: 1 C 76
3: 1 C 22
4: 1 B 32
5: 3 A 24
6: 3 E 15
7: 3 E 42
8: 2 D 42
9: 3 D 37
10: 2 A 16
Run Code Online (Sandbox Code Playgroud)
我应该写什么DT1[ …
加入data.tables 时如何处理同名的非键列?我正在寻找table.field
SQL 中符号的解决方案。
例如,假设我有一个表 DT,v
每个时间段都会为列重新填充新数据。我还有一个表 DT_HIST,用于存储以前时间段 ( t
) 的条目。我想找到每个时间段当前和上一个时间段之间的差异x
在这种情况下:DT是时间段3,DT_HIST有时间段1和2:
DT <- data.table(x=c(1,2,3,4),v=c(20,20,35,30))
setkey(DT,x)
DT_HIST <- data.table(x=rep(seq(1,4,1),2),v=c(40,40,40,40,30,25,45,40),t=c(rep(1,4),rep(2,4)))
setkey(DT_HIST,x)
> DT
x v
1: 1 20
2: 2 20
3: 3 35
4: 4 30
> DT_HIST
x v t
1: 1 40 1
2: 1 30 2
3: 2 40 1
4: 2 25 2
5: 3 40 1
6: 3 45 2
7: 4 40 1
8: 4 40 2
Run Code Online (Sandbox Code Playgroud)
我想加盟DT
与 …