R从数据中获取值的最快方式.表下的多个条件



我试图获得最快的(并在某种程度上优雅)的方法来提取单个元素的数据。几个标准下的表(支持表)。

为了简单起见,一个明显缩短的例子:

library(data.table)
dt <- data.table(
person   = c("Rick", "Michelle", "Richard", "Ryan", "Larry"),
criteria = c("A", "B", "C", "A", "C"),
number   = c(5, 62, 25, 77, 91),
gender   = c("M", "F", "M", "M", "M")
)
supp.dt <- data.table(
crits = c("A", "B", "C"),
ID    = c("ID.1", "ID.2", "ID.3")
)
value.dt <- data.table(
ID.1M = runif(100, 0, 1),
ID.1F = runif(100, 0, 1),
ID.2M = runif(100, 1, 2),
ID.2F = runif(100, 1, 2),
ID.3M = runif(100, 2, 3),
ID.3F = runif(100, 2, 3)
)
getValue <- function(crit=NULL, numb=NULL, gend=NULL) {
return(value.dt[numb, paste0(supp.dt[crits == crit]$ID, gend), with = F])
}
dt$value <- mapply(getValue, dt$criteria, dt$number, dt$gender)

基准和结果:

library(microbenchmark)
runmapply <- function() {
dt$value <- mapply(getValue, dt$criteria, dt$number, dt$gender)
}
microbenchmark(
runmapply()
)
# Unit: milliseconds
# expr        min    lq    mean     median uq     max       neval
# runmapply() 5.5528 5.979 7.912311 6.4392 8.4442 24.1152   100

这里的方法似乎是正确的,但是

  • 我的数据有多达百万行
  • 我需要提取多个值,实际上我使用13不同的值;我将它们存储为数据列表。表和

总之,对于数据量和不同的值来说,它花费的时间太长了。

提前感谢您对优化的任何建议。

更新:

我想塑造和连接桌子。但不知道该怎么接近。我想我不知道是什么数据。表所能做的。由于@langtang

更具体地说一下我提到的那13张表:他们有所有的数据。有100行但列数不同的表。我还应该提到列的名称各不相同,因此示例中的列名ID.1到ID.3设置错误。但这可以很容易地通过ID=str_sub(ID, 1, length(ID))来解决。

对于更多的值表,我们可以清楚地看到,标准为我们提供了到support .dt的连接,另一方面,它保存了13个data.表的所有信息。

所以我们可以看一下有两个值的例子。我还稍微改变了一下这些列名:

library(data.table)
dt <- data.table(
person   = c("Rick", "Michelle", "Richard", "Ryan", "Larry"),
criteria = c("A", "B", "C", "A", "C"),
number   = c(5, 62, 25, 77, 91),
gender   = c("M", "F", "M", "M", "M")
)
supp.dt <- data.table(
crits         = c("A", "B", "C"),
valueoneID    = c("uno", "dos", "tres"),
valuetwoID    = c("eins", "zwei", "drei")
) # for every valuetable there is a respective id column
valueone.dt <- data.table(
unoM  = runif(100, 0, 1),
unoF  = runif(100, 0, 1),
dosM  = runif(100, 1, 2),
dosF  = runif(100, 1, 2),
tresM = runif(100, 2, 3),
tresF = runif(100, 2, 3)
)
valuetwo.dt <- data.table(
einsM = runif(100, 0, 1),
einsF = runif(100, 0, 1),
zweiM = runif(100, 1, 2),
zweiF = runif(100, 1, 2),
dreiM = runif(100, 2, 3),
dreiF = runif(100, 2, 3)
)

我期望的输出应该是这样的:(ID列是不必要的)

gender   person   number  valueone  valuetwo 
<char>   <char>   <int>   <num>     <num>
1: M        Rick     5       0.8572478 0.2312414      
2: M        Ryan     77      0.6211473 0.8585884
3: F        Michelle 62      1.8570321 1.2232323
4: M        Richard  25      2.5732931 2.2323179
5: M        Larry    91      2.0300149 2.0919987

我认为这种方法将取决于您的多个值的确切结构(13,以及它们存储的位置),但您可以考虑使用连接等。

melt(value.dt[, number:=.I],id.vars = "number", variable.name = "ID")[
,`:=`(ID=str_sub(ID, 1,4), gender=str_sub(ID,-1,-1))][
dt[supp.dt,on=c("criteria"="crits")],
on=.(ID,gender,number)]

输出:

number     ID     value gender   person criteria
<int> <char>     <num> <char>   <char>   <char>
1:      5   ID.1 0.8572478      M     Rick        A
2:     77   ID.1 0.6211473      M     Ryan        A
3:     62   ID.2 1.8570321      F Michelle        B
4:     25   ID.3 2.5732931      M  Richard        C
5:     91   ID.3 2.0300149      M    Larry        C

更新如果您有多个"value"帧,你可以采取以下方法:

首先,将它们放入命名列表

value_frames = list("valueoneID" = valueone.dt,"valuetwoID" = valuetwo.dt)

其次,创建单个value.dt数据。从value_frames

中行绑定这些不同帧的熔化版本的表
value.dt = rbindlist(
lapply(value_frames, (f) melt(f[,number:=.I], id.vars="number", variable.name="ID")),
idcol = "vsrc"
)

然后,将value.dt连接到dtsupp.dt之间的连接的熔化版本,并将结果投射回wide。

dcast(
value.dt[,`:=`(ID = str_sub(ID,1,-2), gender=str_sub(ID,-1,-1))][
melt(dt[supp.dt,on=c("criteria"="crits")],
measure.vars = patterns("value"),
variable.name = "vsrc",
value.name = "ID"),
on=.(ID,gender,number,vsrc)],
gender+person+number~vsrc, value.var="value"
)

相关内容

  • 没有找到相关文章

最新更新