【问题标题】:R: updating cell values in dataframe1 based on corresponding cell values in dataframe2R:根据dataframe2中相应的单元格值更新dataframe1中的单元格值
【发布时间】:2015-12-09 16:54:57
【问题描述】:

我有两个相同尺寸的数据框(120 万行 x 5000 列)。这些数据帧 df1 和 df2 的子集如下:

df1<-data.frame(A=c(0,0,1),B=c(0,1,0),C=c(2,1,0),D=c(0,NA,0),E=c(1,0,1))
rownames(df1) <- c("A1", "A2", "B1")
df1
#   A B C  D E
# A1 0 0 2  0 1
# A2 0 1 1 NA 0
# B1 1 0 0  0 1

df2<-data.frame(A=c(106,NA,61),B=c(127,22,10), C=c(9,NA,126), D=c(1,77,54), E=c(99,87,2))
rownames(df2) <- c("A1", "A2", "B1")
df2
#     A   B   C  D  E
# A1 106 127   9  1 99
# A2  NA  22  NA 77 87
# B1  61  10 126 54  2

我想根据 df2 中的相应值更新 df1 中的值,如下所示: 如果 df2 中的单元格值为 NA 或 df2 中的单元格值小于等于 10,则将 df1 中的对应值更改为 NA。否则,保持 df1 中的值不变。

我能够获得一个逻辑数据框,我认为我可以将其用作某种查找表:

df1A <- df1
df1A <- ifelse(df2<=10, df1==NA, df1==df1)
# A    B    C    D    E
# A1 TRUE TRUE   NA   NA TRUE
# A2   NA TRUE   NA   NA TRUE
# B1 TRUE   NA TRUE TRUE   NA

在 df1A 中,每个 TRUE 单元格对应于 df1 中应保持不变的值,每个 NA 单元格对应于 df1 中应更改为(或保持为)NA 的值。但是,我不确定如何使用 df1A 来更新 df1。也不确定这是否是该任务最有效的方法。

任何建议将不胜感激。

【问题讨论】:

    标签: r


    【解决方案1】:

    简单的方法。

    df1[is.na(df2)|df2<=10] <- NA
    df1
    #     A  B  C  D  E
    # A1  0  0 NA NA  1
    # A2 NA  1 NA  0  0
    # B1  1 NA  0  0 NA
    

    【讨论】:

      【解决方案2】:

      Map 的一种方式:

      #Map works like a 'double' lapply
      #in a sense that in each iteration the same
      #column (in terms of the index) for each data.frame
      #will be passed on to x and y
      df1[] <- Map(function(x,y) {
        #y reflects the columns of df2
        #so if y is na or less or equal to 10 then return NA else df1
        ifelse(is.na(y) | y<=10, NA, x)
        },
        df1, df2)
      

      输出:

      > df1
          A  B  C  D  E
      A1  0  0 NA NA  1
      A2 NA  1 NA  0  0
      B1  1 NA  0  0 NA
      

      【讨论】:

      • 谢谢!您的输出没有 A2、D 单元格作为 NA(就像在原始 df1 中一样),但是当我最终提交脚本时,它是完美的!一个后续问题:适用于此脚本的数据框的大小是否有任何限制?当我使用这些大型数据帧尝试其他一些程序时,我得到了“尚不支持长向量:”错误。
      • 不客气,很高兴我能帮上忙 :)。当您定义df1 时,您不小心在问题中输入了D=c(0,0,0),这就是那里没有NA 的原因。 data.frames 的大小没有特别限制,只要它们可以适合您的 RAM。
      【解决方案3】:

      这是使用setdata.table 方法。它应该是有效的,因为避免了[.data.table 中的开销。我们将第一个数据集转换为 data.table (setDT(df1)),然后在 for 循环中遍历列。

      library(data.table)
      setDT(df1)
      for(j in seq_along(df1)){
        set(df1, i= which(is.na(df2[[j]])|df2[[j]]<=10), j=j, value=NA)
       }
      df1
      #    A  B  C  D  E
      #1:  0  0 NA NA  1
      #2: NA  1 NA  0  0
      #3:  1 NA  0  0 NA
      

      【讨论】:

      • 如果效率很重要,像往常一样data.table 应该是最好的。
      • @LyzanderR 我想发布作为 OP 提到的关于 cmets 中的大型数据集的答案。希望它会很有用。也为你 +1。
      • @LyzanderR 在处理大型数据集时,matrix 方法会消耗内存(如果我没记错的话),所以我会选择 Map 作为第二个。
      • @KDA 如果你需要data.frame,你可以在替换后直接做setDF(df1)
      • 你是对的@akrun 谢谢,没想到这个。
      猜你喜欢
      • 2020-05-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-11
      • 1970-01-01
      • 2013-12-27
      • 1970-01-01
      相关资源
      最近更新 更多