【问题标题】:Reshaping into long form when there are no column names for certain repetition当没有特定重复的列名时,重新整形为长格式
【发布时间】:2023-04-07 10:53:01
【问题描述】:

我有一个以下示例数据集,我正在尝试使用 data.table 包重塑为长格式(请不要使用 dplyr 解决方案)。

test_data<-structure(list(id = c("a", "b", "c", "d"), demo_d1_alt = c(2, 
3, 4, 5), demo_d1_pre = c(5, 4, 5, 5), demo_d2_alt = c(4, 5, 
6, 7), demo_d3_alt = c(8, 9, 10, 11), demo_d3_pre = c(5, 5, 5, 
5)), .Names = c("id", "demo_d1_alt", "demo_d1_pre", "demo_d2_alt", 
"demo_d3_alt", "demo_d3_pre"), class = c("tbl_df", "tbl", "data.frame"
), row.names = c(NA, -4L))

id  demo_d1_alt demo_d1_pre demo_d2_alt demo_d3_alt demo_d3_pre
a   2   5   4   8   5
b   3   4   5   9   5
c   4   5   6   10  5
d   5   5   7   11  5

以下是我的代码和输出:

library(data.table)
data_long <- melt.data.table(
     setDT(test_data), id.vars = "id", 
     measure.vars = patterns(alt = "alt",
                             prec= "pre"))
data_long
    id variable alt prec
 1:  a        1   2    5
 2:  b        1   3    4
 3:  c        1   4    5
 4:  d        1   5    5
 5:  a        2   4    5
 6:  b        2   5    5
 7:  c        2   6    5
 8:  d        2   7    5
 9:  a        3   8   NA
10:  b        3   9   NA
11:  c        3  10   NA
12:  d        3  11   NA

我的预期输出是(因为只有 demo_d2 没有 prec)

data_long
    id variable alt prec
 1:  a        1   2    5
 2:  b        1   3    4
 3:  c        1   4    5
 4:  d        1   5    5
 5:  a        2   4    NA
 6:  b        2   5    NA
 7:  c        2   6    NA
 8:  d        2   7    NA
 9:  a        3   8   5
10:  b        3   9   5
11:  c        3  10   5
12:  d        3  11   5

请提出建议。

【问题讨论】:

标签: r data.table reshape


【解决方案1】:

目前,大多数 R 方法并不能很好地处理这些类型的不平衡数据集,而是要求您首先将数据转换为“长”格式,进行一些转换,然后再返回“宽”格式.为此,我编写了 merged.stack 函数作为我的“splitstackshape”包的一部分,之所以如此命名,是因为它首先将 stack 相关的数据列放入 list,然后将 merge 它们放在一起。

方法类似于:

library(splitstackshape)
merged.stack(test_data, var.stubs = c("_alt", "_pre"), sep = "var.stubs", atStart = FALSE)
#     id .time_1 _alt _pre
#  1:  a demo_d1    2    5
#  2:  a demo_d2    4   NA
#  3:  a demo_d3    8    5
#  4:  b demo_d1    3    4
#  5:  b demo_d2    5   NA
#  6:  b demo_d3    9    5
#  7:  c demo_d1    4    5
#  8:  c demo_d2    6   NA
#  9:  c demo_d3   10    5
# 10:  d demo_d1    5    5
# 11:  d demo_d2    7   NA
# 12:  d demo_d3   11    5

但是,随着“data.table”对melt 的改进,重新审视这种方法是有意义的。

工作草案可以在here找到,可以通过以下方式加载相关功能:

source("https://gist.githubusercontent.com/mrdwab/ceded54b616bdc61cb0f/raw/c5a583267f8682a5afea1b551347eafdab618471/MELT.R")

用法很简单:指定数据集、存根以及存根位于变量名的开头还是结尾。

library(data.table)
ReshapeLong_(test_data, stubs = c(alt = "_alt", pre = "_pre"), end_stub = TRUE)
#     id variable alt pre
#  1:  a  demo_d1   2   5
#  2:  b  demo_d1   3   4
#  3:  c  demo_d1   4   5
#  4:  d  demo_d1   5   5
#  5:  a  demo_d2   4  NA
#  6:  b  demo_d2   5  NA
#  7:  c  demo_d2   6  NA
#  8:  d  demo_d2   7  NA
#  9:  a  demo_d3   8   5
# 10:  b  demo_d3   9   5
# 11:  c  demo_d3  10   5
# 12:  d  demo_d3  11   5

【讨论】:

    【解决方案2】:

    简单的 hack 将是

    test_data <- as.data.table(test_data)
    test_data[,.NA:=NA]
    melt(test_data, id='id', 
         measure = list(c('demo_d1_alt', 'demo_d2_alt', 'demo_d3_alt'),
                        c('demo_d1_pre', '.NA', 'demo_d3_pre')))
    

    手动对齐变量并在没有观察到的地方插入“.NA”。

    如果有多个缺失变量,

    test_data <- as.data.table(test_data)
    test_data[,.NA:=NA]
    melt(test_data, id='id', 
         measure = list(c('demo_d1_alt', 'demo_d2_alt', '.NA'),
                        c('demo_d1_pre', '.NA', 'demo_d3_pre')))
    

    【讨论】:

      【解决方案3】:

      一种选择是melt/dcast

      dcast(melt(setDT(test_data), measure = patterns("d\\d+"))[,
          c("var1", "var2") := tstrsplit(variable, "_")[-1]], 
             id + var1 ~ var2, value.var = 'value')[order(var1)]
      #    id var1 alt pre
      # 1:  a   d1   2   5
      # 2:  b   d1   3   4
      # 3:  c   d1   4   5
      # 4:  d   d1   5   5
      # 5:  a   d2   4  NA
      # 6:  b   d2   5  NA
      # 7:  c   d2   6  NA
      # 8:  d   d2   7  NA
      # 9:  a   d3   8   5
      #10:  b   d3   9   5
      #11:  c   d3  10   5
      #12:  d   d3  11   5
      

      【讨论】:

      • 谢谢。那么,melt 一个人处理不了?
      • @Metrics 要使您的代码正常工作,应该有相应的成对列。在这里,我们最后有 d3_pre。因此,它认为这是“d2_alt”的成对列。为了避免这种情况,在转换为 data.table 之前创建一列 NA,即 cbind(test_data[1:4], demo_d2_pre = NA_real_, test_data[5:6])
      • 非常感谢。这很有效,因为我只有一个要创建的变量。
      猜你喜欢
      • 1970-01-01
      • 2019-01-22
      • 1970-01-01
      • 2022-08-14
      • 2021-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-11
      相关资源
      最近更新 更多