【问题标题】:How to move cells with a value row-wise to the left in a dataframe [duplicate]如何在数据框中将具有值的单元格按行向左移动[重复]
【发布时间】:2014-12-26 09:53:18
【问题描述】:

我正在处理一个基本上看起来像这样的数据框。


   X1   X2   X3 X4
x1  a    b   NA  c
x2  d   NA   NA  e
x3  f    g    h  i
x4  j   NA    k  l

我想要做的是将每个具有值的单元格按行向左移动。最后,所有有值的单元格都应该聚集到左边,而所有有 NA 的单元格都应该聚集到右边。

最后,数据框应该是这样的:


   X1   X2   X3 X4
x1  a    b   c  NA
x2  d    e   NA NA
x3  f    g    h  i
x4  j    k    l NA

不幸的是,我不知道该怎么做。

非常感谢您的帮助。 (也许你也可以解释一下你的代码在做什么?)

拉米

【问题讨论】:

  • 我想知道这是否与this 重复。虽然我们在那里没有看到@Anandas 的新功能

标签: r dataframe


【解决方案1】:

也可以试试length<-

df[] <- t(apply(df, 1, function(x) `length<-`(na.omit(x), length(x))))
df
#    X1 X2   X3   X4
# x1  a  b    c <NA>
# x2  d  e <NA> <NA>
# x3  f  g    h    i
# x4  j  k    l <NA>

【讨论】:

    【解决方案2】:

    您可以从我的"SOfun" package 中获取我的naLast function。

    结果将是 matrix,但如果需要,您可以轻松地将其包装在 as.data.frame 中:

    as.data.frame(naLast(mydf, by = "row"))
    #    X1 X2   X3   X4
    # x1  a  b    c <NA>
    # x2  d  e <NA> <NA>
    # x3  f  g    h    i
    # x4  j  k    l <NA>
    

    安装包:

    library(devtools)
    install_github("mrdwab/SOfun")
    

    【讨论】:

    • 它是矢量化还是在下面运行循环?
    • @DavidArenburg,需要再次查看代码。如果我没记错的话,它会在将数据集按行或列拆分后使用矩阵索引,具体取决于所需的内容。
    【解决方案3】:
    yourdata[]<-t(apply(yourdata,1,function(x){
                               c(x[!is.na(x)],x[is.na(x)])}))
    

    应该起作用:对于每一行,它用一个向量替换该行,该向量首先由不是 NA 的值组成,然后是 NA 值。

    【讨论】:

    • 我认为使用x 而不是rowofdata 会使您的代码更具可读性
    • 我编辑了我的答案,谢谢@DavidArenburg 的建议!
    • 我也认为你应该做yourdata[]&lt;- insted of yourdata&lt;-,否则它会将数据转换为matrix
    • 再次编辑......再次感谢@DavidArenburg!和使用as.data.frame一样吗?
    【解决方案4】:

    您可以在不循环 R 的情况下执行此操作。假设您有一个矩阵 m,在这种情况下它可能比 data.frame 更合适。然后,我们只使用order 在行内排序,这样 NA 值排在最后。由于 R 中的排序是保守的,因此保留了非 NA 值的顺序。

    v <- m[order(row(m), is.na(m))]
    dim(v) <- dim(m)
    t(v)
    ##     [,1] [,2] [,3] [,4]
    ## [1,] "a"  "b"  "c"  NA  
    ## [2,] "d"  "e"  NA   NA  
    ## [3,] "f"  "g"  "h"  "i" 
    ## [4,] "j"  "k"  "l"  NA  
    

    要实现数百万行的性能,您可能需要使用基数排序。不幸的是,目前限制(为什么?)为 100,000 个唯一值,但它看起来像:

    v2 <- m[sort.list(is.na(m) + (row(m)-1L)*2L + 1L, method="radix")]
    

    【讨论】:

      【解决方案5】:

      如果你不介意 for 循环:

      ddf
         X1   X2   X3 X4
      x1  a    b <NA>  c
      x2  d <NA> <NA>  e
      x3  f    g    h  i
      x4  j <NA>    k  l
      
      nddf = ddf
      for(i in 1:nrow(ddf))
       nddf[i,] = sort(ddf[i,], na.last=T)
      
      nddf
         X1 X2   X3   X4
      x1  a  b    c <NA>
      x2  d  e <NA> <NA>
      x3  f  g    h    i
      x4  j  k    l <NA>
      

      如果不想排序:

      rowfn = function(rr){
       rr2 = rr; j=1
       for(i in 1:length(rr))    if(!is.na(rr[i])){ rr2[j] = rr[i] ;  j = j+1 } 
       if(j<(length(rr)+1)) for(k in j:length(rr))   rr2[k] = NA
       rr2
       }
      
      ddf
         X1   X2   X3 X4
      x1  a    b <NA>  c
      x2  d <NA> <NA>  e
      x3  f    g    h  i
      x4  j <NA>    k  l
      
      nddf = ddf
      for(i in 1:nrow(ddf)) nddf[i,] = rowfn(ddf[i,])
      
      nddf
         X1 X2   X3   X4
      x1  a  b    c <NA>
      x2  d  e <NA> <NA>
      x3  f  g    h    i
      x4  j  k    l <NA>
      

      【讨论】:

      • 这假设他们想要对值进行排序,不是吗?
      • 另外,如果你要对值进行排序,我想你可以使用na.last 参数..
      • 排序功能后 NA 似乎消失了。适用于 sort(x, na.last=T)。更正了上面的代码。
      • 在上面的答案中添加了一个没有排序的解决方案。
      • (+1) 永远不会让我们忘记 R 中也有 for 循环 :)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-06-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多