【问题标题】:R: Merge several columns into one, with one value on each row [duplicate]R:将几列合并为一列,每行有一个值[重复]
【发布时间】:2016-08-25 02:58:10
【问题描述】:

现在我有一个这样的数据框:

   Z    A  B  C  D  F
1  82   1 NA NA NA 77
2 454  NA  2 NA NA 18
3 606  NA NA  3 NA 12
4  55  NA NA NA  4 23
5  32  NA  2 NA NA  4
# And many more rows follows

A、B、C、D 列中只有一个列在每一行上都有值,并且每一列内的值相同。我想将它们合并为一列,1、2、3、4 将成为这一新列的因子水平。

期望的结果:

   Z    A  B  C  D  F  E
1  82   1 NA NA NA 77  1
2 454  NA  2 NA NA 18  2
3 606  NA NA  3 NA 12  3
4  55  NA NA NA  4 23  4
5  32  NA  2 NA NA  4  2
# And many more rows follows
# Dropping A,B,C,D as a side-effect is OK

我尝试过使用ifelse 语句(data$E = ifelse(data$A == 1, 5, data$A),但是每个ifelse 语句都会覆盖之前的修改,所以最后只将级别 4 写入 E 列。

有什么优雅的方法可以合并这些列吗?删除 A、B、C、D 作为副作用是可以的。谢谢!

编辑:如果我在左侧和右侧有更多不相关的列怎么办?是否需要某种切片? (见编辑代码)

【问题讨论】:

    标签: r dataframe merge


    【解决方案1】:

    只要每一行只有一个值,rowSums 就可以工作:

    df$E <- rowSums(df, na.rm = TRUE)
    
    df
    ##    A  B  C  D E
    ## 1  1 NA NA NA 1
    ## 2 NA  2 NA NA 2
    ## 3 NA NA  3 NA 3
    ## 4 NA NA NA  4 4
    ## 5 NA  2 NA NA 2
    

    【讨论】:

    • 谢谢,但是如果我的 df 中有额外的列与这个新建的列无关怎么办?我需要先将列切掉才能完成吗?
    • 调用中的df 子集:rowSums(df[ , 2:5], na.rm = T)
    • 谢谢,我用笨办法做到了df$E &lt;- colSums(df[c("A", "B", "C", "D")], na.rm = T) 现在运行良好。
    • 没关系。尤其是如果您有很多列,使用名称进行子集化可能是一种更安全且不易混淆的方法。
    【解决方案2】:

    我们可以将pmaxpminna.rm = TRUE 一起使用

    df1$E <- do.call(pmax, c(df1, na.rm=TRUE))
    df1
    #   A  B  C  D E
    #1  1 NA NA NA 1
    #2 NA  2 NA NA 2
    #3 NA NA  3 NA 3
    #4 NA NA NA  4 4
    #5 NA  2 NA NA 2
    

    我们也可以使用max.col(在这个例子中我们不需要cbind与行索引)

    max.col(!is.na(df1))
    #[1] 1 2 3 4 2
    

    一般

    df1[cbind(1:nrow(df1), max.col(!is.na(df1)))]
    

    或者我们可以使用%*% 来获取每行非NA元素的列索引

    (+(!is.na(df1)) %*% seq_along(df1))[,1]
    

    如果我们使用hadleyversecoalesce 也可以提供帮助

    library(dplyr)
    df1 %>% 
         mutate(E = coalesce(A, B, C, D))
    #   A  B  C  D E
    #1  1 NA NA NA 1
    #2 NA  2 NA NA 2
    #3 NA NA  3 NA 3
    #4 NA NA NA  4 4
    #5 NA  2 NA NA 2
    

    或者data.table的另一个选项

    library(data.table)
    setDT(df1)[, E := na.omit(unlist(.SD)) ,1:nrow(df1)]
    

    注意:此解决方案基于 OP 的初始示例/预期输出以及本文的 titleR:将多列合并为一列,每行有一个值

    数据

    df1 <- structure(list(A = c(1L, NA, NA, NA, NA), B = c(NA, 2L, NA, NA, 
    2L), C = c(NA, NA, 3L, NA, NA), D = c(NA, NA, NA, 4L, NA)), .Names = c("A", 
    "B", "C", "D"), class = "data.frame", row.names = c("1", "2", 
    "3", "4", "5"))
    

    【讨论】:

      猜你喜欢
      • 2022-11-19
      • 1970-01-01
      • 1970-01-01
      • 2015-06-20
      • 2012-05-12
      • 1970-01-01
      • 1970-01-01
      • 2021-01-23
      • 1970-01-01
      相关资源
      最近更新 更多