【问题标题】:retaining names of levels of variables while melting [duplicate]在熔化时保留变量级别的名称[重复]
【发布时间】:2018-06-22 12:25:54
【问题描述】:

有什么方法可以保留正在融化的变量的原始级别的名称?例如,在下面的示例中,有什么方法可以得到“alpha”、“beta”和“gamma”,而不是“1”、“2”、“3”。

当然,我可以重命名它们,但我正在使用的数据集有大量关卡,因此重命名它们既费时又容易出错。

谢谢。

library(data.table)
#> Warning: package 'data.table' was built under R version 3.4.2
set.seed(2334)

# define the dataframe
df <-
  as.data.frame(
    cbind(
      a_alpha = rnorm(10),
      a_beta = rnorm(10),
      a_gamma = rnorm(10),
      b_alpha = rnorm(10),
      b_beta = rnorm(10),
      b_gamma = rnorm(10),
      id = c(1:10)
    )
  )

# check the structure of the wide format data
str(df)
#> 'data.frame':    10 obs. of  7 variables:
#>  $ a_alpha: num  -0.118 1.237 0.809 -0.766 -0.592 ...
#>  $ a_beta : num  0.0019 1.0639 2.336 0.9056 0.6449 ...
#>  $ a_gamma: num  0.5485 0.8345 -0.5977 0.0827 0.2754 ...
#>  $ b_alpha: num  0.209 -0.305 0.434 -0.362 0.412 ...
#>  $ b_beta : num  -1.6404 2.8382 0.0661 0.7249 -0.4421 ...
#>  $ b_gamma: num  -0.144 0.964 -0.763 -1.356 0.995 ...
#>  $ id     : num  1 2 3 4 5 6 7 8 9 10

# convert to long format
df_long <- data.table::melt(
  data.table::setDT(df),
  measure = patterns("^a_", "^b_"),
  value.name = c("a", "b"),
  variable.name = "item"
)

# check the structure of the long format data
str(df_long)
#> Classes 'data.table' and 'data.frame':   30 obs. of  4 variables:
#>  $ id  : num  1 2 3 4 5 6 7 8 9 10 ...
#>  $ item: Factor w/ 3 levels "1","2","3": 1 1 1 1 1 1 1 1 1 1 ...
#>  $ a   : num  -0.118 1.237 0.809 -0.766 -0.592 ...
#>  $ b   : num  0.209 -0.305 0.434 -0.362 0.412 ...
#>  - attr(*, ".internal.selfref")=<externalptr>

# structure of item
levels(df_long$item)
#> [1] "1" "2" "3"

# Question: instead of "1" "2" "3", how to get the "item" factor levels to be: "alpha" "beta" "gamma"

reprex package (v0.1.1.9000) 于 2018 年 1 月 12 日创建。

【问题讨论】:

  • 我不确定您认为 data.table 会从哪里获得 "alpha" "beta" "gamma" 字符串,因为它们在您的原始表中不存在(以那种形式)。
  • 看看this 以获得一些灵感。您基本上必须使用factormatch 或类似的东西。
  • 我认为这是两个包如何找到列的结果...data.tablegrep 过于灵活,无法可靠地提取所需的列名部分(尽管它可以在你的情况下工作)。而 sep 版本可以隐式发送到 strsplit 以根据需要将字符串分开。由于简约,灵活性就丧失了。
  • @Henrik 非常感谢!!!这对我完全有用:)
  • @IndrajeetPatil 请注意我已更新my answer in the linked question。从data.table 1.14.1 开始,新函数measure 保留了连接变量名的原始字符串。

标签: r data.table reshape melt


【解决方案1】:

我过去处理这个问题的方法是在melt 处理数据之后使用factor。但是,您可能需要进行一些检查以确保数据和级别的顺序正确。

这是一个例子:

set.seed(2334)
df <- data.table(a_alpha = rnorm(10), a_beta = rnorm(10), a_gamma = rnorm(10),
                 b_alpha = rnorm(10), b_beta = rnorm(10), b_gamma = rnorm(10), 
                 id = c(1:10))
df_mess <- copy(df)
setcolorder(df_mess, c(1, 7, 6, 4, 2, 5, 3))
names(df_mess)
# [1] "b_alpha" "id"      "a_alpha" "a_beta"  "b_beta"  "b_gamma" "a_gamma"

stubs <- c("^a_", "^b_")
## assumes all stubs have same number of cols. Easy to modify
labs <- grep(stubs[1], names(df_mess), value = TRUE) 
labs <- gsub(paste(stubs, collapse = "|"), "", labs[order(labs)])

out1 <- melt(df, measure.vars = patterns(stubs), value.name = c("a", "b"), 
             variable.name = "item")[
               , item := factor(item, labels = labs)][]

out2a <- melt(df_mess, measure.vars = patterns(stubs), value.name = c("a", "b"), 
              variable.name = "item")[
                , item := factor(item, labels = labs)][]

out2b <- melt(setcolorder(df_mess, names(df_mess)[order(names(df_mess))]),
     measure.vars = patterns(stubs), value.name = c("a", "b"), 
     variable.name = "item")[
       , item := factor(item, labels = labs)][]

library(compare)
compare(out1, out2a)
# FALSE [TRUE, TRUE, TRUE, FALSE]
compare(out1, out2b)
# TRUE

我还没有做足够多的测试用例来自信地说在nameslevs 上使用order 是否足以满足所有情况,但到目前为止,我不仅在数据时发现异常不平衡。

【讨论】:

    猜你喜欢
    • 2018-06-02
    • 2016-01-05
    • 1970-01-01
    • 2021-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-25
    相关资源
    最近更新 更多