【问题标题】:How to create a string from row values in a dataframe ignoring NAs如何从忽略 NA 的数据框中的行值创建字符串
【发布时间】:2014-11-04 16:36:34
【问题描述】:

这是我的数据框:

x1 <- c("a", "c", "f", "j")
x2 <- c("b", "c", "g", "k")
x3 <- c("b", "d", "h", NA)
x4 <- c("a", "e", "i", NA)
df <- data.frame(x1, x2, x3, x4, stringsAsFactors=F)

df

  x1 x2   x3   x4
1  a  b    b    a
2  c  c    d    e
3  f  g    h    i
4  j  k <NA> <NA>

使用

apply(df, 1, paste, collapse = "_")

给我

[1] "a_b_b_a"   "c_c_d_e"   "f_g_h_i"   "j_k_NA_NA"

我想忽略 NA,所以最后一个结果元素应该是“j_k”而不是“j_k_NA_NA”。

非常感谢您的支持。

拉米

【问题讨论】:

    标签: r dataframe


    【解决方案1】:

    使用您的代码,

    apply(df, 1, function(x) paste(na.omit(x), collapse="_") )
    #[1] "a_b_b_a" "c_c_d_e" "f_g_h_i" "j_k"    
    

    另一种选择是

    df[is.na(df)] <-''
     gsub("^_+|_+$", "", do.call(paste,c(df, sep="_")))
    #[1] "a_b_b_a" "c_c_d_e" "f_g_h_i" "j_k"  
    

    编辑

    如果有内部 NA,也许这可行

    gsub("^_+|_+$|_+(?=_)", "", do.call(paste,c(df, sep="_")), perl=TRUE)
    

    或基于@David Arenburg 的 cmets

    gsub("NA_|_NA", "", apply(df, 1, paste, collapse = "_"))
    

    例如

    v1 <- c(NA,'a', 'b', NA, NA, NA, 'c',NA, 'd', NA)
    v1[is.na(v1)] <-''
    gsub("^_+|_+$|_+(?=_)", "", paste(v1, collapse="_"), perl=TRUE)
    #[1] "a_b_c_d"
    

    【讨论】:

    • +1。你的第二个选择似乎是要走的路。第一个会因为在包含许多行的数据集上重复调用 na.omit 而受到影响。
    • 您的最后一个 gsub 需要进行一些修改,以便在内部列中捕获多个后续 NA 值。
    • @Ananda Mahto 感谢 cmets。我确实更新了gsub。希望它会起作用,尽管没有进行广泛的测试。
    • 也可以gsub("_NA", "", apply(df, 1, paste, collapse = "_"))
    • @David Arenburg 我认为需要修改gsub("_NA", "", paste(v1, collapse="_"))#[1] "NA_a_b_c_d" 可能是gsub("NA_|_NA", "", paste(v1, collapse="_"))
    【解决方案2】:

    这是使用zoo 包的建议

    library(zoo)
    gsub("NA_|_NA", "", rollapply(t(df), width = 4, FUN = paste, collapse = "_"))
    ##      [,1]      [,2]      [,3]      [,4] 
    ## [1,] "a_b_b_a" "c_c_d_e" "f_g_h_i" "j_k"
    

    【讨论】:

    • 我还没有将它添加到我的基准测试中,但我觉得它可能很慢 (?)
    • @AnandaMahto,可能是因为t,但我不确定。我认为在这种情况下它并不重要
    【解决方案3】:

    @akrun 的第二个选项很可能是最快的,但您也可以考虑这样的事情:

    library(data.table)
    na.omit(data.table(
      rn = rep(1:nrow(df), ncol(df)), 
      val = unlist(df, use.names = FALSE)))[, paste(val, collapse = "_"), by = rn]
    #    rn   value
    # 1:  1 a_b_b_a
    # 2:  2 c_c_d_e
    # 3:  3 f_g_h_i
    # 4:  4     j_k
    

    基本思想是从“长”data.table 开始,删除 NA 值,然后将剩余的值粘贴在一起。

    在此特定示例中,在速度方面,您使用na.omit 会产生很大的不同。


    更新

    以下是使用相同样本数据(10 万行)I shared at a related question 的一些基准测试。

    这些是我测试的功能:

    AM <- function() {
      na.omit(data.table(
        rn = rep(1:nrow(df), ncol(df)), 
        val = unlist(df, use.names = FALSE)))[, paste(val, collapse = "_"), by = rn]
    }
    
    AK <- function() {
      df[is.na(df)] <-''
      gsub("^_+|_+$|_+(?=_)", "", do.call(paste,c(df, sep="_")), perl=TRUE)
    }
    
    RS <- function() {
      s <- split(df[!is.na(df)], row(df)[!is.na(df)])
      vapply(s, paste, character(1L), collapse = "_", USE.NAMES=FALSE)
    }
    

    结果:

    microbenchmark(AM(), AK(), RS(), times = 50)
    # Unit: milliseconds
    #  expr       min        lq      mean    median        uq      max neval
    #  AM()  819.4639  925.1636 1020.5084  979.6239 1118.8065 1384.873    50
    #  AK()  490.6802  495.5576  559.4551  508.0861  602.8413 1192.798    50
    #  RS() 1419.8630 1540.5424 1680.6115 1622.7701 1786.9931 2424.541    50
    

    【讨论】:

    • 嗯,考虑到前几天的事件,这个问题很有趣。 :)
    【解决方案4】:

    您可以在删除了 NA 值的列表上使用 vapply。这似乎是安全的。

    > s <- split(df[!is.na(df)], row(df)[!is.na(df)])
    > vapply(s, paste, character(1L), collapse = "_", USE.NAMES=FALSE)
    [1] "a_b_b_a" "c_c_d_e" "f_g_h_i" "j_k"   
    

    【讨论】:

    • 这个答案还不是万无一失的。第一列中的单个NAs 或NAs 怎么样?还有更多gsubbing 要做:-)
    • @AnandaMahto - 我完全走向了不同的方向。这可能更安全
    • 不确定我是否会认为这是一条完全不同的路线。从概念上讲,它共享我的答案的一些属性:创建两个向量,其中一个用于将需要粘贴在一起的值分组。你的是基本 R 中的字面拆分 + 应用 + 组合,而我对“data.table”做同样的事情。但是 +1 用于编辑和我没有想到的 row 的创造性使用 :-) @akrun 的答案仍然是迄今为止最快的,当使用 sample dataset at my earlier answer from today 进行测试时(请参阅我的更新。)跨度>
    猜你喜欢
    • 2019-06-11
    • 1970-01-01
    • 2021-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-19
    • 2020-10-27
    • 2018-04-24
    相关资源
    最近更新 更多