Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/google-chrome/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 根据包含列名的变量从不同列中选择值_R_Data.table - Fatal编程技术网

R 根据包含列名的变量从不同列中选择值

R 根据包含列名的变量从不同列中选择值,r,data.table,R,Data.table,我有一个data.table,如下所示: col1 col2 col3 new 1 4 55 col1 2 3 44 col2 3 34 35 col2 4 44 87 col3 我想填充另一列matched_value,该列包含new列中给出的各个列名中的值: col1 col2 col3 new matched_value 1 4 55

我有一个data.table,如下所示:

col1   col2   col3  new  
1       4     55    col1 
2       3     44    col2
3       34    35    col2
4       44    87    col3
我想填充另一列
matched_value
,该列包含
new
列中给出的各个列名中的值:

col1   col2   col3  new    matched_value
1       4     55    col1        1
2       3     44    col2        3
3       34    35    col2        34
4       44    87    col3        87 
例如,在第一行中,
new
的值为“col1”,因此
matched_值
col1
中取值,即1


如何在R中对一个非常大的数据表有效地执行此操作?

我们可以将“新”列与数据集的列名进行匹配,以获得列索引,
cbind
与行索引(
1:nrow(df1)
)并基于行/列索引提取数据集的相应元素。可以将其指定给新列

df1$matched_value <- df1[-4][cbind(1:nrow(df1),match(df1$new, colnames(df1) ))]
df1
#  col1 col2 col3  new matched_value
#1    1    4   55 col1             1
#2    2    3   44 col2             3
#3    3   34   35 col2            34
#4    4   44   87 col3            87
基准
set.seed(45)

df2使用晦涩的
.BY
的借口:

DT[, newval := .SD[[.BY[[1]]]], by=new]

   col1 col2 col3  new newval
1:    1    4   55 col1      1
2:    2    3   44 col2      3
3:    3   34   35 col2     34
4:    4   44   87 col3     87
它是如何工作的。这将根据
new
中的字符串将数据拆分为组。每个组的字符串值存储在
newname=.BY[[1]]
中。我们使用此字符串通过
.SD[[newname]]
选择
.SD
的相应列
.SD
代表S数据集Data


替代品
get(.BY[[1]])
应该可以替代
.SD[.BY[[1]]]]
。根据@David运行的一个基准测试,这两种方法同样快。

您能给出一个等效的数据表语法吗?还有,它会很快吗?我有一个非常大的数据集,大约有2000万行。@user3664020行/列索引速度很快,但是
cbind
ing可能是一个瓶颈。你有多少列?5列。这是数据表。可能使用
fastmatch
?大概
new
是一个因素,所以真正需要的是
transform(dat,val=dat[cbind(1:nrow(dat),new)])
。非常快看起来像其他语言。它是如何工作的?等待解释!谢谢+1因为这个解决方案比我的
dt[,matched_value:=as.integer(get(new)),by=1:nrow(dt)]
解决方案快。@David我想
get
可能也一样快(也许更快?)。如果你做了
get(.by[[1]],by=new
@Frank出于好奇,我已经测试了
get(.by[[1]])和
.SD[.by[[1]]
在10^6行上使用
系统时间。这两者在时间上是无法区分的。@Frank请注意,在2020年,
.SD[.BY[[1]]]]]
似乎不再适用于指示找不到
.SD
的消息。幸运的是,
get(.BY[[1]])
继续工作!
set.seed(45)
df2 <- data.frame(col1= sample(1:9, 20e6, replace=TRUE),
col2= sample(1:20, 20e6, replace=TRUE), 
col3= sample(1:40, 20e6, replace=TRUE),
col4=sample(1:30, 20e6, replace=TRUE),
new= sample(paste0('col', 1:4), 20e6, replace=TRUE), stringsAsFactors=FALSE)
system.time(df2$matched_value <- df2[-5][cbind(1:nrow(df2),match(df2$new, colnames(df2) ))])
#   user  system elapsed 
#  2.54    0.37    2.92 
DT[, newval := .SD[[.BY[[1]]]], by=new]

   col1 col2 col3  new newval
1:    1    4   55 col1      1
2:    2    3   44 col2      3
3:    3   34   35 col2     34
4:    4   44   87 col3     87