Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/64.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
基于从现有列派生的TRUE/FALSE设置新列值_R_Data.table - Fatal编程技术网

基于从现有列派生的TRUE/FALSE设置新列值

基于从现有列派生的TRUE/FALSE设置新列值,r,data.table,R,Data.table,我想在data.table对象中创建一个新列,并且应该根据匹配范围内的数字来设置值。范围的from和to是现有数据表中的两列 [数据] library(data.table) set.seed(1) DT <- data.table(from=sample(10000))[, to:=from+sample(10000)] > head(DT) from to 1: 2656 3304 2: 3721 10487 3: 5728 13081 4: 9080 10193 5:

我想在
data.table
对象中创建一个新列,并且应该根据匹配范围内的数字来设置值。范围的
from
to
是现有
数据表中的两列

[数据]

library(data.table)
set.seed(1)
DT <- data.table(from=sample(10000))[, to:=from+sample(10000)]

> head(DT)
from    to
1: 2656  3304
2: 3721 10487
3: 5728 13081
4: 9080 10193
5: 2017  2484
6: 8980 10289
[问题]

library(data.table)
set.seed(1)
DT <- data.table(from=sample(10000))[, to:=from+sample(10000)]

> head(DT)
from    to
1: 2656  3304
2: 3721 10487
3: 5728 13081
4: 9080 10193
5: 2017  2484
6: 8980 10289
代码运行需要一些时间,正如您所想象的,如果
sample(n)
中的
n
变得更大,则需要更多的时间


我的问题是:有更好的方法吗?在速度和代码可读性方面更好(我相信我的代码一点都不直观)。

对不起,为什么不这样做:

DT[,flag:=0]
DT[from<=6500 & to>=6500,flag:=1]
DT[,标志:=0]
DT[from=6500,标志:=1]
除非我不理解你的问题,否则结果应该是一样的。

为什么不使用:

DT[, flag := +(from < 6500 & to > 6500)]
另一种可能性(由@Frank提出):

然而,
mapply
调用会导致相当大的开销。仅使用:

DT[, flag := between(6500,from,to)]
从以下不同方法之间的速度比较中可以看出,速度要快得多:

library(microbenchmark)
microbenchmark(q = DT[, flag:=0][DT[, .I[6500 %in% seq(from, to, by=1)], by=1:nrow(DT)][[1]], flag:=1],
               j1 = DT[, flag := +(from < 6500 & to > 6500)],
               j2 = DT[, flag := ifelse(from < 6500 & to > 6500, 1, 0)],
               j3 = DT[, flag := mapply(between,6500,from,to)],
               j4 = DT[, flag := between(6500,from,to)],
               nikos = DT[, flag:=0][from<=6500 & to>=6500, flag:=1],
               jimbo = DT[, flag := 6500<=to & 6500>=from])

Unit: microseconds
  expr         min           lq         mean       median           uq         max
     q 2424842.405 2498646.2495 2638230.4775 2545083.2020 2684601.6290 4336768.458
    j1     843.639     896.2505    1074.3921     955.3120    1047.0570    3689.399
    j2    2063.674    2205.7850    2766.0470    2282.0050    3115.9475    7978.479
    j3   16072.188   16406.6920   19550.4140   19056.4665   20915.1620   75465.362
    j4     687.094     731.7385     877.6009     780.1280     858.3825    3073.322
 nikos    1077.945    1186.2395    1424.4156    1290.7015    1389.8500    3699.621
 jimbo     759.372     836.2075    1000.6322     884.4715     958.0035    3016.492
库(微基准)
微基准(q=DT[,标志:=0][DT[,.I[6500%在%序列中(从,到,由=1)],由=1:nrow(DT)][[1]],标志:=1],
j1=DT[,标志:=+(从<6500到>6500)],
j2=DT[,标志:=ifelse(从<6500到>6500,1,0)],
j3=DT[,flag:=mapply(介于,6500,from,to之间)],
j4=DT[,标志:=介于(6500,从,到)]之间,
nikos=DT[,标志:=0][from=6500,标志:=1],
jimbo=DT[,标志:=6500=from])
单位:微秒
expr最小lq平均uq最大中值
q 2424842.4052498646.24952638230.47752545083.2020 2684601.62904336768.458
j1 843.639 896.2505 1074.3921 955.3120 1047.0570 3689.399
j2 2063.674 2205.7850 2766.0470 2282.0050 3115.9475 7978.479
j3 16072.188 16406.6920 19550.4140 19056.4665 20915.1620 75465.362
J4687.094731.7385877.6009780.1280858.38253073.322
尼科斯1077.9451186.23951424.41561290.70151389.85003699.621
金宝759.372 836.2075 1000.6322 884.4715 958.0035 3016.492
因此,最快的方法(j4中的
between
选项)比问题中的原始方法快约3000倍。

库(data.table)
library(data.table)
set.seed(1)
DT <- data.table(from=sample(10000))[, to:=from+sample(10000)]
DT[, flag := 6500<=to & 6500>=from]

> table(DT$flag)

FALSE  TRUE 
 5567  4433 
种子(1) DT表(DT$标志) 假真 5567 4433
试试
帮助(“%between%”)
帮助(“%chin%”)
如果你想问一个关于字符的问题,你应该这样做(作为一个新问题)。。。下面的所有答案似乎都能很好地处理您的示例。此外,它们将扩展到字符,因为字符之间的不平等很好,比如
“6500”@Frank,我更新了我的帖子。很抱歉发帖时没有考虑周到。@Frank,我给出了一些想法,不认为我应该创建一个新问题,因为我的标题建议对
数据进行子集设置。表
基于
TRUE
/
FALSE
。这就是我在解决方案中使用
.I(…)
的原因。我最初的例子有误导性,所以我换了一个更相关的。“如果你不同意,请告诉我。”弗兰克说得通。我要问一个新问题。
ifelse
要慢得多though@DavidArenburg这只是为了说明第一句话的作用谢谢你的详细解释。我想说我已经足够好了:)谢谢你公布时间安排。确实很有趣。您还可以将其简化为
DT[,flag:=0][from=6500,flag:=1]
library(microbenchmark)
microbenchmark(q = DT[, flag:=0][DT[, .I[6500 %in% seq(from, to, by=1)], by=1:nrow(DT)][[1]], flag:=1],
               j1 = DT[, flag := +(from < 6500 & to > 6500)],
               j2 = DT[, flag := ifelse(from < 6500 & to > 6500, 1, 0)],
               j3 = DT[, flag := mapply(between,6500,from,to)],
               j4 = DT[, flag := between(6500,from,to)],
               nikos = DT[, flag:=0][from<=6500 & to>=6500, flag:=1],
               jimbo = DT[, flag := 6500<=to & 6500>=from])

Unit: microseconds
  expr         min           lq         mean       median           uq         max
     q 2424842.405 2498646.2495 2638230.4775 2545083.2020 2684601.6290 4336768.458
    j1     843.639     896.2505    1074.3921     955.3120    1047.0570    3689.399
    j2    2063.674    2205.7850    2766.0470    2282.0050    3115.9475    7978.479
    j3   16072.188   16406.6920   19550.4140   19056.4665   20915.1620   75465.362
    j4     687.094     731.7385     877.6009     780.1280     858.3825    3073.322
 nikos    1077.945    1186.2395    1424.4156    1290.7015    1389.8500    3699.621
 jimbo     759.372     836.2075    1000.6322     884.4715     958.0035    3016.492
library(data.table)
set.seed(1)
DT <- data.table(from=sample(10000))[, to:=from+sample(10000)]
DT[, flag := 6500<=to & 6500>=from]

> table(DT$flag)

FALSE  TRUE 
 5567  4433