【问题标题】:reshaping k columns to 2 columns representing sequential pairs of the values of the k variables将 k 列重塑为 2 列,表示 k 个变量的值的顺序对
【发布时间】:2017-12-07 06:22:30
【问题描述】:

我有一个这样的数据框:

id y1 y2 y3 y4  
--+--+--+--+--
a |12|13|14|  
b |12|18|  |
c |13|  |  |
d |13|14|15|16  

我想以这样一种方式重塑,以两列结束。上面的例子会变成:

id from to  
--+----+--- 
a |12  |13  
a |13  |14  
a |14  |
b |12  |18
b |18  |  
c |13  |
d |13  |14  
d |14  |15  
d |15  |16  

每个id 的每对年份值都有一个“来自”和一个“至”。
有谁知道一个简单的方法来做到这一点?我尝试使用reshape2。我还查看了Combine Multiple Columns Into Tidy Data,但我认为我的情况不同。

【问题讨论】:

    标签: r reshape data-management


    【解决方案1】:

    您可以使用lapply 循环列对并使用rbind 合并它们:

    do.call(rbind,
            lapply(2:(length(df)-1), 
                   function(x) setNames(df[!is.na(df[,x]),c(1,x,x+1)], 
                                        c("id", "from", "to"))))
       id from to
    1   a   12 13
    2   b   12 18
    3   c   13 NA
    4   d   13 14
    11  a   13 14
    21  b   18 NA
    41  d   14 15
    12  a   14 NA
    42  d   15 16
    

    【讨论】:

      【解决方案2】:

      解决方案使用dplyrtidyrdt2 是最终输出。

      # Create example data frame
      dt <- data.frame(id = c("a", "b", "c", "d"),
                       y1 = c(12, 12, 13, 13),
                       y2 = c(13, 18, NA, 14),
                       y3 = c(14, NA, NA, 15),
                       y4 = c(NA, NA, NA, 16),
                       stringsAsFactors = FALSE)
      
      # Load packages
      library(dplyr)
      library(tidyr)
      
      # Process the data
      dt2 <- dt %>%
        gather(STEP, from, -id) %>%
        drop_na(from) %>%
        arrange(id, STEP) %>%
        group_by(id) %>%
        mutate(to = lead(from)) %>%
        select(-STEP)
      

      【讨论】:

      • 整洁,虽然会产生额外的一行
      • @HubertL 感谢您的评论。我知道最后一行不在 OP 所需的输出中,但我觉得它应该在那里。至少我没有找到一个很好的逻辑来排除最后一行,因为最后一行 id abc 也在那里。
      • 不应该,因为它的to 值是由lead 生成的。重排:df %&gt;% gather(var, from, -id) %&gt;% arrange(id, var) %&gt;% group_by(id) %&gt;% mutate(to = lead(from)) %&gt;% #slice(-n()) %&gt;% filter(!is.na(from), var != 'y4') %&gt;% select(-var)
      • 如果id=="b"18-NA 行,我看不出id=="d" 不应该有16-NA 行。
      • @alistaire 感谢您的建议。让我们等待OP对此的澄清。目前,我同意@thelatemail。如果 18-NA 在 id b 中,16-NA 也应该在 id d 中。
      【解决方案3】:

      在基础 R 中,stack 并将每组中的所有内容移回一行。使用@ycw 的示例数据,dt

      tmp <- na.omit(cbind(dt[1], stack(dt[-1])[-2]))
      names(tmp)[2] <- "from"
      tmp$to <- with(tmp, ave(from, id, FUN=function(x) c(tail(x,-1),NA) ))
      tmp[order(tmp$id),]
      
      #   id from to
      #1   a   12 13
      #5   a   13 14
      #9   a   14 NA
      #2   b   12 18
      #6   b   18 NA
      #3   c   13 NA
      #4   d   13 14
      #8   d   14 15
      #12  d   15 16
      #16  d   16 NA
      

      data.table 的世界中,同样的逻辑也适用。 melt,然后是shift by= id:

      library(data.table)
      dt <- as.data.table(dt)
      
      melt(dt, id.vars="id", value.name="from")[
        !is.na(from),-"variable"][, to := shift(from,1,type="lead"), by=id
      ][order(id)]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-01-23
        • 1970-01-01
        • 2019-12-07
        • 2018-04-17
        • 1970-01-01
        • 1970-01-01
        • 2020-11-25
        • 1970-01-01
        相关资源
        最近更新 更多