【问题标题】:R - Fill columns in dfR - 填充 df 中的列
【发布时间】:2016-07-03 16:47:09
【问题描述】:
                a                      b                  P116 P127 P125 P107 P101 P220 P135                                 
1 P116,P115,P113,P120,P112,  P128,P125,P127,P123,P126,    NA   NA   NA   NA   NA   NA   NA
2 P116,P115,P113,P120,P112,  P128,P125,P127,P123,P126,    NA   NA   NA   NA   NA   NA   NA 
3 P120,P117,P116,P115,P119,      P98,P94,P96,P99,P93,     NA   NA   NA   NA   NA   NA   NA
4      P34,P36,P40,P39,P37,  P108,P106,P107,P110,P109,    NA   NA   NA   NA   NA   NA   NA
5 P123,P127,P125,P118,P198,  P135,P132,P134,P138,P131,    NA   NA   NA   NA   NA   NA   NA
6 P142,P148,P149,P140,P150,      P80,P81,P89,P87,P86,     NA   NA   NA   NA   NA   NA   NA

我有一个数据框,其中 a 和 b 列的一些值与其他列的名称匹配。我想用数字替换 NA: 1(如果“a”列的行中的值与 3:9 列的名称匹配),0(如果“a”、“b”列中的值与 3:9 列的名称不匹配),-1(如果值在“b”列的行中匹配列的名称 3:9)

它应该看起来像这样。

              a                          b               P116 P127 P125 P107 P101 P220 P135                          
1 P116,P115,P113,P120,P112,  P128,P125,P127,P123,P126,    1    -1   -1   0    0    0    0
2 P116,P115,P113,P120,P112,  P128,P125,P127,P123,P126,    1    -1   -1   0    0    0    0 
3 P120,P117,P116,P115,P119,      P98,P94,P96,P99,P93,     1     0    0   0    0    0    0
4      P34,P36,P40,P39,P37,  P108,P106,P107,P110,P109,    0     0    0  -1    0    0    0
5 P123,P127,P125,P118,P198,  P135,P132,P134,P138,P131,    0     1    1   0    0    0   -1
6 P142,P148,P149,P140,P150,      P80,P81,P89,P87,P86,     0     0    0   0    0    0    0

【问题讨论】:

  • 如果“a”和“b”列都匹配会发生什么?
  • 在这个数据框中没有发生。

标签: r fill na


【解决方案1】:

我们可以试试

df[-(1:2)] <- Reduce(`+`,Map(`*`, lapply(c("a", "b"), function(nm) 
       do.call(rbind, lapply(strsplit(df[[nm]], ","), function(x)
         +(names(df)[-(1:2)] %in% x)))), c(1, -1)))
 df
 #                          a                         b P116 P127 P125 P107 P101 P220 P135
 #1 P116,P115,P113,P120,P112, P128,P125,P127,P123,P126,    1   -1   -1    0    0    0    0
 #2 P116,P115,P113,P120,P112, P128,P125,P127,P123,P126,    1   -1   -1    0    0    0    0
 #3 P120,P117,P116,P115,P119,      P98,P94,P96,P99,P93,    1    0    0    0    0    0    0
 #4      P34,P36,P40,P39,P37, P108,P106,P107,P110,P109,    0    0    0   -1    0    0    0
 #5 P123,P127,P125,P118,P198, P135,P132,P134,P138,P131,    0    1    1    0    0    0   -1
 #6 P142,P148,P149,P140,P150,      P80,P81,P89,P87,P86,    0    0    0    0    0    0    0

【讨论】:

    【解决方案2】:

    我没有正确测试它,在较大的数据集上它可能会很慢,但这是我非常不像 R 的尝试:

    假设您的数据框名为df

    for (row in 1:nrow(df)) {
        for (col in 3:ncol(df)) {
            if (grepl(colnames(df)[col], df[row, "a"])) {
                df[row, col] <- 1
            } else if (grepl(colnames(df)[col], df[row, "b"])) {
                df[row, col] <- -1
            } else {
                df[row, col] <- 0
            }
        }
    }
    

    如果ab 中的字符串与列名匹配,则循环并使用grepl 返回逻辑匹配。

    【讨论】:

      【解决方案3】:

      这是一种经过测试的功能方法。

      鉴于您的数据框:

      df=data.frame(a=c(
          "P116,P115,P113,P120,P112,", 
          "P116,P115,P113,P120,P112,", 
          "P120,P117,P116,P115,P119,", 
          "     P34,P36,P40,P39,P37,", 
          "P123,P127,P125,P118,P198,", 
          "P142,P148,P149,P140,P150,"    
        ),
        b=c(
          "P128,P125,P127,P123,P126,", 
          "P128,P125,P127,P123,P126,", 
          "     P98,P94,P96,P99,P93,", 
          "P108,P106,P107,P110,P109,", 
          "P135,P132,P134,P138,P131,",    
          "     P80,P81,P89,P87,P86," 
        ),    
        P116=NA, P127=NA, P125=NA, P107=NA, P101=NA, P220=NA, P135=NA,
        stringsAsFactors=FALSE)
      

      解决办法是:

      sel=lapply(as.list(df[, 1:2]), function(col)
          t(sapply(col, function(x) match(strsplit(x, "," )[[1]], names(df)[-(1:2)], nomatch=0))))
      dfm=as.matrix(df[, -(1:2)])
      k=-1
      lapply(sel, function(selr){
          i<<-0;  k<<-k*-1
          apply(selr, 1, function(j) {
              i <<- i+1
              dfm[cbind(i,j)]<<- k
          })}
          )
      dfm[is.na(dfm)]=0     
      df[, -(1:2)]=dfm
      

      你得到:

      df
                                  a                         b  P116 P127 P125 P107 P101 P220 P135  
      ## 1 P116,P115,P113,P120,P112, P128,P125,P127,P123,P126,    1   -1   -1    0    0    0    0 
      ## 2 P116,P115,P113,P120,P112, P128,P125,P127,P123,P126,    1   -1   -1    0    0    0    0 
      ## 3 P120,P117,P116,P115,P119,      P98,P94,P96,P99,P93,    1    0    0    0    0    0    0 
      ## 4      P34,P36,P40,P39,P37, P108,P106,P107,P110,P109,    0    0    0   -1    0    0    0 
      ## 5 P123,P127,P125,P118,P198, P135,P132,P134,P138,P131,    0    1    1    0    0    0   -1 
      ## 6 P142,P148,P149,P140,P150,      P80,P81,P89,P87,P86,    0    0    0    0    0    0    0 
      

      请下次使用dput(&lt;your dataframe&gt;) 让您的问题更容易回答。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-12-29
        • 2018-12-11
        • 2021-03-25
        • 2023-01-17
        • 1970-01-01
        • 2021-11-05
        • 2022-08-14
        相关资源
        最近更新 更多