我有两个data.tables,X(3米行乘500列)和Y(100行乘两列).
set.seed(1)
X <- data.table( a=letters, b=letters, c=letters, g=sample(c(1:5,7),length(letters),replace=TRUE), key="g" )
Y <- data.table( z=runif(6), g=1:6, key="g" )
Run Code Online (Sandbox Code Playgroud)
我想在X上做一个左外连接,我可以做到Y[X]这一点,感谢:
为什么X [Y]连接data.tables不允许完全外连接或左连接?
但我想在X 不复制的情况下添加新列X(因为它很大).
显然,像X <- Y[X]作品这样的东西,但除非data.table比我给它的功劳更加明确(并且我非常狡猾地给予它赞美!),我相信这复制了整个X.
X[ , z:= Y[X,z]$z ] 虽然工作正常,但却不能很好地扩展到多个列.
如何将合并的结果以有效的方式(在副本方面和程序员时间方面)存储回保留的data.table中?
考虑
target <- "vs"
value <- 1
library(data.table)
dt <- as.data.table(head(mtcars))
Run Code Online (Sandbox Code Playgroud)
所以我试图将列名和值作为变量传递到环境中的j表达式中data.table,这相当于
dt[, vs == 1]
# [1] FALSE FALSE TRUE TRUE FALSE TRUE
Run Code Online (Sandbox Code Playgroud)
如果只有值是变量,它可以很好地工作
dt[, vs == value]
# [1] FALSE FALSE TRUE TRUE FALSE TRUE
Run Code Online (Sandbox Code Playgroud)
当它是变量时,我们也可以在data.table范围内调用该列
dt[, target, with = FALSE]
# vs
# 1: 0
# 2: 0
# 3: 1
# 4: 1
# 5: 0
# 6: 1
Run Code Online (Sandbox Code Playgroud)
但我无法想象如何以简单的方式将两者结合起来
注意:我很清楚我可以做到:
dt[[target]] == value
# [1] FALSE FALSE TRUE TRUE FALSE …Run Code Online (Sandbox Code Playgroud) 我正在探索使用data.table包装聚合函数(但实际上它可以是任何类型的函数)的不同方法(也提供了一个dplyr示例)并且想知道关于函数式编程/元编程的最佳实践
基本应用是灵活地聚合表,即参数化变量以聚合,聚合的维度,两者的相应结果变量名称和聚合函数.我已经在三个data.table和一个dplyr方式中实现了(几乎)相同的功能:
图书馆
library(data.table)
library(dplyr)
Run Code Online (Sandbox Code Playgroud)
数据
n_size <- 1*10^6
sample_metrics <- sample(seq(from = 1, to = 100, by = 1), n_size, rep = T)
sample_dimensions <- sample(letters[10:12], n_size, rep = T)
df <-
data.frame(
a = sample_metrics,
b = sample_metrics,
c = sample_dimensions,
d = sample_dimensions,
x = sample_metrics,
y = sample_dimensions,
stringsAsFactors = F)
dt <- as.data.table(df)
Run Code Online (Sandbox Code Playgroud)
实现
1. fn_dt_agg1
fn_dt_agg1 <-
function(dt, metric, metric_name, dimension, dimension_name) { …Run Code Online (Sandbox Code Playgroud) 我已经搜索了规范的方法来做我正在尝试的东西,但我似乎没有运气得到快速和优雅的工作.简而言之,我有一个包含多个值列的大表,并希望将每个值乘以查找表中的相应因子.我无法弄清楚如何动态传递我想要的列乘以查找值,或者如何在基本表达式之外引用查询值.
这是我的例子,我设置了300万行,有10个值列,这不需要太长时间,并且有点代表数据大小(这将作为更大的循环的一部分实现,因此强调关于表现).我们的value_1:value_10列还有一个包含6个级别和一些匹配乘数的查找表.
library(data.table)
setsize <- 3000000
value_num <- 10
factors <- c("factor_a", "factor_b", "factor_c", "factor_d", "factor_e", "factor_f")
random <- data.table(replicate(10, sample(factors, size = setsize, replace = T))
, replicate(10, rnorm(setsize, mean = 700, sd = 50)))
lookup <- data.table("V1" = factors, replicate(10, seq(.90, 1.5, length.out = length(factors))))
wps <- paste("value", c(1:10), sep = "_")
names(random)[11:20] <- wps
names(lookup)[2:11] <- wps
setkeyv(random, "V1")
setkeyv(lookup, "V1")
Run Code Online (Sandbox Code Playgroud)
解决方案1:它相当快,但我无法弄清楚如何一般地引用i-columns,i.value_1因此我可以将它们传递到循环中或更好地同时应用它们.
f <- function() {
random[lookup, value_1 := value_1 * i.value_1, by = .EACHI] …Run Code Online (Sandbox Code Playgroud) 在 data.table 中,可以直接处理当前数据表(比如 DT)而无需创建它的副本。例如,这可以在创建新列时完成。
DT[,new_col:=1]
Run Code Online (Sandbox Code Playgroud)
我想知道如何进行合并,特别是左连接。比如左连接的数据表方式是
DT_right[DT_left,on="id"]
Run Code Online (Sandbox Code Playgroud)
但是,这不会修改原始的 DT_left 表,需要我重新分配。IE
DT_left = DT_right[DT_left,on="id"]
Run Code Online (Sandbox Code Playgroud)
有没有办法让我在不重新分配的情况下做到这一点?即直接在 DT_left 上工作。
df1 <- data.frame(w = 1:4, x = c("a", "b", "b", "c"), y = NA)
df1$y[df1$x == "c"] = 1
df2 <- data.frame(x = c("a", "b"), y = 1:2, z = 3:4)
Run Code Online (Sandbox Code Playgroud)
我想用df2中的值更新df1以匹配行,包括所有df2列.
预期结果:
df1
w x y z
1 1 a 1 3
2 2 b 2 4
3 3 b 2 4
4 4 c 1 NA
Run Code Online (Sandbox Code Playgroud)
这是我的尝试:
# add missing columns from df2 to df1
df1[setdiff(colnames(df2), colnames(df1))] <- NA
# update values in df1 from df2 for matching …Run Code Online (Sandbox Code Playgroud)