【问题标题】:In data.table: iterating over the rows of another data.table在 data.table 中:迭代另一个 data.table 的行
【发布时间】:2023-04-02 23:20:02
【问题描述】:

我有两个data.tables:

k1 <- mtcars[1:4,1:6]
k11 <- as.data.table(k1)
k2 <- iris[1:3,1:2]
k22 <- as.data.table(k2)

我正在尝试通过迭代第二个 data.table 的列行来对第一个 data.table 执行一些列操作

k3 <- lapply(1:nrow(k2),function(j){
  mpg=k1[,"mpg"]*k2[j,"Sepal.Width"] #get the new value of mpg equals to mpg*first row of second column of second data.frame
  cyl=k1[,"cyl"]*k2[j,"Sepal.Width"]
  a3=k1[,3:6] #all remaining columns over which no operations are done 
  a4<-cbind(mpg,cyl,a3) #cbind these and create a new dataframe for each row of second dataframe. There are three rows and hence there will be three final dataset

})
#rbind all these dataset and get the new dataset
k4<-do.call(rbind,k3)

head(k4)
                  mpg  cyl disp  hp drat    wt
Mazda RX4       73.50 30.6  160 110 3.90 2.620
Mazda RX4 Wag   73.50 30.6  160 110 3.90 2.875
Datsun 710      79.80 20.4  108  93 3.85 2.320
Hornet 4 Drive  74.90 30.6  258 110 3.08 3.215

虽然上面的解决方案很完美,但我想知道:

  1. 使用data.table是否有效率增益(因为这里没有group_by操作)第一个数据帧为30000乘以10,#second数据帧为60乘以4(最终数据集将有30000次60:180 万行)。
  2. 如果有效率增益,使用data.table如何获得效率:

以下是我的解决方案(类似于data.frame)

k5<-rbindlist(lapply(1:nrow(k2),function(j){

  k11[,`:=`(mpg=mpg*k22[j,Sepal.Width],cyl=cyl*k22[j,Sepal.Length])]

}))

 head(k5)
      mpg     cyl disp  hp drat    wt
1: 705.60 704.718  160 110 3.90 2.620
2: 705.60 704.718  160 110 3.90 2.875
3: 766.08 469.812  108  93 3.85 2.320
4: 719.04 704.718  258 110 3.08 3.215
5: 705.60 704.718  160 110 3.90 2.620
6: 705.60 704.718  160 110 3.90 2.875

你可以看到答案是不同的(我猜是因为 data.table 的复制性质)。

【问题讨论】:

    标签: r data.table


    【解决方案1】:

    您可以使用set(这会很有效,因为可以避免[.data.table 中的开销)并在使数据集具有相同的行数后执行*

    library(data.table)
    k1N <- k11[rep(1:.N,nrow(k22))]
    k2N <- k22[rep(1:.N,each=nrow(k11))][, 2:1]
    
    for(j in 1:2){
     set(k1N, i=NULL, j=j, value=k1N[[j]]*k2N[[j]])
    }
    
    k1N
    #      mpg  cyl disp  hp drat    wt
    # 1: 73.50 30.6  160 110 3.90 2.620
    # 2: 73.50 30.6  160 110 3.90 2.875
    # 3: 79.80 20.4  108  93 3.85 2.320
    # 4: 74.90 30.6  258 110 3.08 3.215
    # 5: 63.00 29.4  160 110 3.90 2.620
    # 6: 63.00 29.4  160 110 3.90 2.875
    # 7: 68.40 19.6  108  93 3.85 2.320
    # 8: 64.20 29.4  258 110 3.08 3.215
    # 9: 67.20 28.2  160 110 3.90 2.620
    #10: 67.20 28.2  160 110 3.90 2.875
    #11: 72.96 18.8  108  93 3.85 2.320
    #12: 68.48 28.2  258 110 3.08 3.215
    

    【讨论】:

    • 感谢您的回答。这适用于k11 的单列(mpg),但正如您在我的问题中看到的那样,我还需要对k11 的第二列(cyl)执行此操作。特别是,第二第一个数据表的列 (k11) 需要乘以第二个数据表的 Sepal.Length 列 (k22)。我该怎么做?
    • @user227710 我根据k4 的结果进行了编码。我得到的结果看起来和k4一样。我的意思是应用你的代码。不是您使用 head(k4) 显示的结果
    • akrun:不,cyl 列的情况不一样。在您的解决方案中,cyl 列中的值不会更改。
    • @user227710 请运行您的代码并检查答案。我得到的只是相同的价值
    • @user227710 好的,感谢您的澄清。我也这么认为,但是被你的代码弄糊涂了
    猜你喜欢
    • 1970-01-01
    • 2014-01-08
    • 2018-09-15
    • 1970-01-01
    • 1970-01-01
    • 2023-03-27
    • 2021-06-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多