【问题标题】:Get all combinations of some column's values and column names into one row将某些列的值和列名的所有组合放入一行
【发布时间】:2019-07-19 22:41:12
【问题描述】:

我有一个数据框列表,所有这些都是相同的维度(64 obs,12 个变量)。我需要以这样一种方式“展平”这些数据框,即我返回 64 x 11 = 704 个变量和一个观察值,推导出具有所有唯一值的一列和数据框的列名的所有组合。示例如下。

我尝试使用acastmelt 来实现这一点。但是,当必须将这种方法应用到超过 100k+ 数据帧时,熔化前和熔化后的支持操作会使这种方法变慢。

这是一个示例数据框和我采取的方法:

df <- data.frame(var1=c(1,2,3),name=c("these","are","names"),var3=c(4,NA,NA),var4=c(NA,NA,5),var6=c(NA,5,NA))

flattening <- function(df){
  rownames(df) <- df$name
  df$name <- NULL
  df <- melt(as.matrix(df)) %>% group_by(name = paste0(Var1,"_",Var2)) %>% summarise(
    value = first(value)
  ) %>% data.frame()

  cnames <- df$name
  df <- data.frame(values=df$value) %>% t() %>% data.frame()
  names(df) <- cnames
  df
}

flattening(df)

示例 df 如下所示:

  var1  name var3 var4 var6
1    1 these    4   NA   NA
2    2   are   NA   NA    5
3    3 names   NA    5   NA

我正在寻找预期的结果:

       are_var1 are_var3 are_var4 are_var6 names_var1 names_var3 names_var4 names_var6 these_var1 these_var3 these_var4 these_var6
values        2       NA       NA        5          3         NA          5         NA          1          4         NA         NA

结果更新:

我在下面有一个微基准,expr 是用户的句柄:

Unit: milliseconds
   expr       min        lq      mean    median        uq        max neval cld
    old 78.370093 81.038799 90.272721 85.694885 89.304528 1114.03968   500   c
 tmfmnk 11.829791 12.697675 13.844833 13.134485 13.623065   34.91430   500  b 
    s_t  1.476159  1.774409  2.030418  1.873876  2.003681   16.89159   500 a 

【问题讨论】:

    标签: r dataframe


    【解决方案1】:

    dplyrtidyr 选项可以是:

    df %>%
     gather(var, val, -2) %>%
     mutate(var = paste(name, var, sep = "_")) %>%
     select(-name) %>%
     spread(var, val)
    
      are_var1 are_var3 are_var4 are_var6 names_var1 names_var3 names_var4 names_var6
    1        2       NA       NA        5          3         NA          5         NA
      these_var1 these_var3 these_var4 these_var6
    1          1          4         NA         NA
    

    它应该比你原来的方法更快,但是,肯定有更快的可能性。

    【讨论】:

      【解决方案2】:

      你也可以使用reshape2::melt() 然后使用base R:

      library(reshape2)
      dats <- melt(df) 
      rownames(dats) <- paste0(dats$name,'-',dats$variable)
      dats <- t(dats)
      dats <- dats[-c(1,2),]
      dats <- sapply(dats,as.numeric)
      dats
      
      these-var1   are-var1 names-var1 these-var3   are-var3 names-var3 these-var4   are-var4 names-var4 these-var6   are-var6 
               1          2          3          4         NA         NA         NA         NA          5         NA          5 
      names-var6 
              NA 
      

      编辑

      这里是data.frame

      dats <- as.data.frame.matrix(t(as.data.frame.numeric(dats)))
      

      【讨论】:

      • 到目前为止,您的解决方案是最有效的。让我们看看是否有人可以胜过它。但是,我必须将以下内容添加到 sapply 阶段以适合我的用例(我在数据框列表中使用 lapply 与您的解决方案)。你有机会找到更快的选择吗? dats &lt;- data.frame(t(sapply(dats,as.numeric)))
      • @JonathanRauscher 不确定,但您可以使用它来将其转换为 data.frame :dats &lt;- as.data.frame.matrix(t(as.data.frame.numeric(dats))) 具有类 data.frame。
      • 效果更好。介意更新你的答案吗?
      【解决方案3】:

      使用来自data.tabledcast 可以采用多个value.var

      library(data.table)
      out <- dcast(setDT(df)[, rn := 1], rn ~ name, 
                value.var = paste0("var", c(1, 3, 4, 6)))[, rn := NULL][]
      setnames(out, sub("([^_]+)_([^_]+)", "\\2_\\1", names(out)))
      out
      #   are_var1 names_var1 these_var1 are_var3 names_var3 these_var3 are_var4 names_var4 these_var4 are_var6 names_var6 these_var6
      #1:        2          3          1       NA         NA          4       NA          5         NA        5         NA         NA
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-08-12
        • 2015-04-10
        • 1970-01-01
        • 2020-09-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-04-02
        相关资源
        最近更新 更多