R:对许多data.frames的操作 - 我如何加速我的代码?

时间:2016-05-16 11:21:23

标签: r list dataframe

我想优化我的代码,因为使用循环需要太长时间。我在下面准备了一个问题方案。

我想比较两个数据帧的第2和第3列中的值。 因此,我希望在比较满足要求的两个数据帧后得到一个表:

如果第一个数据框中第2列的值(df)> =第二个数据框中第2列中的值(df2)和df中第3列中的值< = df2中3r列中的值

所以我的要求:

  

if(df [i,2]> = df2 [j,2]&& df [i,3]< = df2 [j,3])

下面我的代码效果很好并且做了我想要的但是我认为它效率不高。有没有人知道我可以用来改进(加速)我的代码的功能?

#data frames
L1 = c(65, 61, 70, 65)
L2 = c(150, 135, 210, 140)
Name= c("A","A","A","A")
df = data.frame(Name, L1, L2)

L12 = c(70, 63, 52, 65)
L22 = c(132, 135, 145, 150)
Name2 = c("B","B","B","B")
df2 = data.frame(Name2, L12, L22)

temp <- df[FALSE,]
temp1 <- df2[FALSE,]

for (i in 1:nrow(df)){
l = 1
  for (j in 1:nrow(df2)){
    if(df[i,2] >= df2[j,2] && df[i,3] <= df2[j,3]){
     temp[l,] <-df[i,]
     temp1[l,] <-df2[j,]
     l = l + 1
    }
   }
 summ <- cbind(temp, temp1)
  if(i==1){
  sum1 <- summ
  }
  else(sum1 <- rbind(sum1,summ))
temp <- temp[FALSE,]
temp1 <- temp1[FALSE,]
}

此外,我必须逐个比较每个数据帧。我认为最简单的方法是将所有数据框作为列表读取并使用一些功能 - 也许来自申请系列?我试着这样做,但我失败了。我将不胜感激任何提示:)

2 个答案:

答案 0 :(得分:2)

和其他人一样,我并不完全确定我理解你想要什么。我想这就是你追求的目标?

   lapply(1:nrow(df),function(X) 
                     df[X,1]>=df2[,2]&&df[X,1]<df2[,3]
          )

这将返回df中每行的列表,即逻辑测试为真的实例数

 lapply(1:nrow(df),function(X) 
                         sum(df[X,1]>=df2[,2]&&df[X,1]<df2[,3])
              )

此外,您的代码包含一些基本的低效语句(例如,增长数据) - 这对于处理大数据时的速度可能是有害的。然而,有时我们会故意增加数据(最终产品的未知大小),因此您可能是故意这样做的。

无论如何,这是一个简短的已发布beginners guide on efficient R代码,您可以阅读(专注于生物学 - 但适用于所有领域)。

希望这有帮助!

注意:刚刚看过zyurnaidi的编辑。这段代码非常相似,如果df2很小,它将与上面的代码一样高效 - 否则重复合并可能会大大降低速度。

答案 1 :(得分:1)

您可以先合并两个数据帧,然后再进行操作:

df.df2 <- merge(df, df2)
df.df2 <- df.df2[with(df.df2, L1 >= L12 & L2 <= L22), ]
df.df2

   Name L1  L2 Name2 L12 L22
10    A 61 135     B  52 145
12    A 65 140     B  52 145
13    A 65 150     B  65 150
16    A 65 140     B  65 150

编辑:可能这会适用于你的情况,因为它不需要创建一个大的合并数据帧,它一点一点地工作。但是,该过程本身可能需要比原始解决方案更长的时间。

df.df2 <- data.frame()
for(i in 1:nrow(df)) {
  df.df2.i <- merge(df[i, ], df2)
  df.df2.i <- df.df2.i[with(df.df2.i, L1 >= L12 & L2 <= L22), ]
  df.df2 <- rbind(df.df2, df.df2.i)
}

或使用lapply

df.df2 <- lapply(1:nrow(df), function(i) {
  df.df2.i <- merge(df[i, ], df2)
  df.df2.i <- df.df2.i[with(df.df2.i, L1 >= L12 & L2 <= L22), ]
})
df.df2 <- do.call(rbind, df.df2)