我比较熟悉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
x = structure(list(f1 = 1:3, f2 = 3:5), .Names = c("f1", "f2"), row.names = c(NA, -3L), class = c("data.table", "data.frame"))
Run Code Online (Sandbox Code Playgroud)
我想将一个函数应用于每一行data.table.该函数func.test使用args f1并对其f2执行某些操作并返回计算值.假设(作为例子)
func.text <- function(arg1,arg2){ return(arg1 + exp(arg2))}
Run Code Online (Sandbox Code Playgroud)
但我的真实函数更复杂,并且循环和所有,但返回计算值.实现这一目标的最佳方法是什么?
我不能在里面使用switch,mutate因为它返回的是整个向量而不仅仅是行.作为一个黑客,我正在使用:
pick <- function(x, v1, v2, v3, v4) {
ifelse(x == 1, v1,
ifelse(x == 2, v2,
ifelse(x == 3, v3,
ifelse(x == 4, v4, NA))))
}
Run Code Online (Sandbox Code Playgroud)
这在内部工作mutate,现在很好,因为我通常选择4件事,但这可能会改变.你能推荐另一种选择吗?
例如:
library(dplyr)
df.faithful <- tbl_df(faithful)
df.faithful$x <- sample(1:4, 272, rep=TRUE)
df.faithful$y1 <- rnorm(n=272, mean=7, sd=2)
df.faithful$y2 <- rnorm(n=272, mean=5, sd=2)
df.faithful$y3 <- rnorm(n=272, mean=7, sd=1)
df.faithful$y4 <- rnorm(n=272, mean=5, sd=1)
Run Code Online (Sandbox Code Playgroud)
使用pick:
mutate(df.faithful, y = pick(x, y1, y2, y3, y4))
Source: local data frame [272 x 8] …Run Code Online (Sandbox Code Playgroud) 我有两个data.table,两个共享一个变量; 我正在尝试添加第二个缺少的变量,但是它与共享变量一对一地绑定.
这显然是一个合并,但由于共享变量有多个实例,我不得不使用感觉变形的方法来合并新变量.
让我们具体一点.
x <- data.table(let = rep(letters[1:3], 2:4),
num = rep(1:3, 2:4), other = rnorm(9))
y <- data.table(let = rep(c("a", "c"), c(10, 6)))
x:
let num other
1: a 1 -0.41695882
2: a 1 -0.59875888
3: b 2 -0.19433915
4: b 2 0.58406046
5: b 2 -0.33922321
6: c 3 -0.63076561
7: c 3 1.06987710
8: c 3 0.08869372
9: c 3 -1.31196123
y:
let
1: a
2: a
3: a
4: a
5: a
6: …Run Code Online (Sandbox Code Playgroud) 我有两个表,我想以一种等同于以下SQL的方式连接在一起,在这里我加入多个条件,而不仅仅是相等.
require(sqldf)
require(data.table)
dt <- data.table(num=c(1, 2, 3, 4, 5, 6),
char=c('A', 'A', 'A', 'B', 'B', 'B'),
bool=c(TRUE, FALSE, TRUE, FALSE, TRUE, FALSE))
dt_two <- data.table(
num =c(6, 1, 5, 2, 4, 3),
char=c('A', 'A', 'A', 'B', 'B', 'B'),
bool=c(TRUE, FALSE, TRUE, FALSE, TRUE, FALSE))
dt_out_sql <- sqldf('
select dtone.num, dtone.char, dtone.bool, SUM(dttwo.num) as SUM,
MIN(dttwo.num) as MIN
from dt as dtone INNER join dt_two as dttwo on
(dtone.char = dttwo.char) and
(dtone.num >= dttwo.num OR dtone.bool)
GROUP BY dtone.num, …Run Code Online (Sandbox Code Playgroud) 我有一个相对较大的数据帧(~2,000,000行),对于每一行,我需要在该观察组中计算大于或等于当前行值的每个值的总和.
这是一个示例数据框:
sample_df = data.frame(
group_id = c(1,1,1,1,2,2,2,2),
value = c(10,12,14,12,8,8,21,10)
)
Run Code Online (Sandbox Code Playgroud)
我目前有一个非常缓慢的解决方案,使用循环和一些过滤来做到这一点,但是,更好的解决方案是更优选的.我一直在尝试使用dplyr,但我无法弄清楚如何在数据分组后得到其他观察值的总和.
通过上面的玩具示例,这里将是所需的输出:
desired_output = data.frame(
group_id = c(1,1,1,1,2,2,2,2),
value = c(10,12,14,12,8,8,21,10),
output = c(38,26,0,26,39,39,0,21)
)
Run Code Online (Sandbox Code Playgroud)
为了找到已经发布的解决方案,我没有看到一个明确的答案,它解释了如何将一组中的每个观察结果与其他观察结果进行比较,并按照某些标准对该组进行筛选.我更喜欢基于dplyr的解决方案,但如果有高效的base-R或data.table解决方案,我会同样感激!
我正在尝试通过data.table调用替换SQL生成的笛卡尔积.我拥有丰富的资产和价值历史,我需要所有组合的子集.假设我有一个表格,其中T = [date,contract,value].在SQL中它看起来像
SELECT a.date, a.contract, a.value, b.contract. b.value
FROM T a, T b
WHERE a.date = b.date AND a.contract <> b.contract AND a.value + b.value < 4
Run Code Online (Sandbox Code Playgroud)
在RI现在有以下内容
library(data.table)
n <- 1500
dt <- data.table(date = rep(seq(Sys.Date() - n+1, Sys.Date(), by = "1 day"), 3),
contract = c(rep("a", n), rep("b", n), rep("c", n)),
value = c(rep(1, n), rep(2, n), rep(3, n)))
setkey(dt, date)
dt[dt, allow.cartesian = TRUE][(contract != i.contract) & (value + i.value < 4)]
Run Code Online (Sandbox Code Playgroud)
我相信我的解决方案首先创建所有组合(在这种情况下为13,500行),然后过滤(到3000).然而SQL(我可能错了)加入子集,更重要的是不要将所有组合加载到RAM中.任何想法如何使用data.table更有效?
为什么我Rcpp在data.table连接中的函数与在连接之外使用时产生不同(和不正确)的结果?
我有两个data.tables,我想找到两个表中每对坐标之间的欧几里德距离.
为了进行距离计算,我已经定义了两个函数,一个在基数R中,另一个在使用中Rcpp.
library(Rcpp)
library(data.table)
rEucDist <- function(x1, y1, x2, y2) return(sqrt((x2 - x1)^2 + (y2 - y1)^2))
cppFunction('NumericVector cppEucDistance(NumericVector x1, NumericVector y1,
NumericVector x2, NumericVector y2){
int n = x1.size();
NumericVector distance(n);
for(int i = 0; i < n; i++){
distance[i] = sqrt(pow((x2[i] - x1[i]), 2) + pow((y2[i] - y1[i]), 2));
}
return distance;
}')
dt1 <- data.table(id = rep(1, 6),
seq1 = 1:6,
x = c(1:6),
y = …Run Code Online (Sandbox Code Playgroud) 在R 2.15.0和data.table 1.8.9:
d = data.table(a = 1:5, value = 2:6, key = "a")
d[J(3), value]
# a value
# 3 4
d[J(3)][, value]
# 4
Run Code Online (Sandbox Code Playgroud)
我希望两者产生相同的输出(第二个),我相信它们应该.
为了清除这不是J语法问题,同样的期望适用于以下(与上述相同)表达式:
t = data.table(a = 3, key = "a")
d[t, value]
d[t][, value]
Run Code Online (Sandbox Code Playgroud)
我希望以上两个都返回完全相同的输出.
那么让我重新解释一下这个问题 - 为什么(data.table这样设计)关键列会自动打印出来d[t, value]?
更新(根据下面的答案和评论):感谢@Arun等人,我理解设计 - 为什么现在.究其原因,上面打印的关键是因为有一个隐藏的当前每次你做一个时间data.table通过合并X[Y]语法,这by是关键.它以这种方式设计的原因似乎如下 - 因为by必须在合并时执行操作,人们可以利用它而不是另外做另一个,by如果你要通过合并的键来做到这一点.
现在说,我认为这是一个语法设计缺陷.我阅读 …
我有两个数据框ev1和ev2,描述了在许多测试中收集的两种类型事件的时间戳.因此,每个数据帧都有"test_id"和"timestamp"列.我需要找到的是在同一测试中每个ev2的最小距离ev1.
我有一个工作代码合并两个数据集,计算距离,然后使用dplyr过滤最小距离:
ev1 = data.frame(test_id = c(0, 0, 0, 1, 1, 1), time=c(1, 2, 3, 2, 3, 4))
ev2 = data.frame(test_id = c(0, 0, 0, 1, 1, 1), time=c(6, 1, 8, 4, 5, 11))
data <- merge(ev2, ev1, by=c("test_id"), suffixes=c(".ev2", ".ev1"))
data$distance <- data$time.ev2 - data$time.ev1
min_data <- data %>%
group_by(test_id, time.ev2) %>%
filter(abs(distance) == min(abs(distance)))
Run Code Online (Sandbox Code Playgroud)
虽然这很有效,但合并部分非常慢并且感觉效率低下 - 我正在为同一个test_id生成一个包含ev2-> ev1的所有组合的巨大表格,只是将其过滤为一个.在合并期间,似乎应该有一种"即时过滤"的方法.在那儿?
更新:当使用akrun概述的data.table方法时,以下两个"group by"列的情况会失败:
ev1 = data.frame(test_id = c(0, 0, 0, 1, 1, 1), time=c(1, 2, 3, 2, 3, 4), group_id=c(0, …Run Code Online (Sandbox Code Playgroud)