如何在 base R 中重现 pivot_longer 的结果?

How to reproduce the result of pivot_longer with reshape in base R?

考虑 cprefm 对象:

library(conjoint)

data(chocolate)

pivot_longer:

library(dplyr)
library(tidyr)

cprefm %>% 
  pivot_longer(., 1:16, "profile", "rating") %>% 
  head(16)

# A tibble: 16 × 2
   profile   value
   <chr>     <int>
 1 profile1     14
 2 profile2     15
 3 profile3      5
 4 profile4      2
 5 profile5      1
 6 profile6     11
 7 profile7      3
 8 profile8     10
 9 profile9     16
10 profile10    13
11 profile11    12
12 profile12     7
13 profile13     6
14 profile14     9
15 profile15     4
16 profile16     8

我无法使用重塑功能重现此内容:

cprefm |>
  (\(x) reshape(x, varying = 1:16, times = names(x)[1:16], timevar = "profile", 
                v.names = "values", direction = "long"))() |> 
  (\(x) head(x, 16))()

             profile values id
1.profile1  profile1     14  1
2.profile1  profile1     16  2
3.profile1  profile1      7  3
4.profile1  profile1      9  4
5.profile1  profile1      7  5
6.profile1  profile1     14  6
7.profile1  profile1      3  7
8.profile1  profile1      2  8
9.profile1  profile1      1  9
10.profile1 profile1      4 10
11.profile1 profile1      4 11
12.profile1 profile1     14 12
13.profile1 profile1      7 13
14.profile1 profile1     14 14
15.profile1 profile1     10 15
16.profile1 profile1      4 16

我尝试了很多方法来修改 varying 参数,但我无法重现 tidyr::pivot_longer 的行为。请注意,即使 row.names 也有列名,但我也不喜欢那样。

我希望它看起来与 pivot_longer 相同。

如果不使用 reshape 没问题,这可能有效...

x <- as.data.frame(t(cprefm))

y <- data.frame(
  profile = rownames(x),
  value = unlist(x)
)
head(y,16)

     profile value
1   profile1    14
2   profile2    15
3   profile3     5
4   profile4     2
5   profile5     1
6   profile6    11
7   profile7     3
8   profile8    10
9   profile9    16
10 profile10    13
11 profile11    12
12 profile12     7
13 profile13     6
14 profile14     9
15 profile15     4
16 profile16     8

对于 base 中的完整枢轴,我将使用 stack,不编辑 fiddle 使其与 pivot_longer 完全匹配:

result = cprefm |> stack() |> setNames(c("value", "profile")) |> rev() 
result = result[order((1:nrow(result) - 1) %% nrow(cprefm), result$profile), ]
rownames(result) = 1:nrow(result)
result
#      profile value
# 1   profile1    14
# 2   profile2    15
# 3   profile3     5
# 4   profile4     2
# 5   profile5     1
# 6   profile6    11
# 7   profile7     3
# 8   profile8    10
# 9   profile9    16
# 10 profile10    13
# 11 profile11    12
# 12 profile12     7
# 13 profile13     6
# 14 profile14     9
# 15 profile15     4
# 16 profile16     8
# 17  profile1    16
# 18  profile2    15
# 19  profile3     7
# 20  profile4    14
# ...

1) post process 问题中的 reshape 命令产生相同的输出,除了行名、行顺序和一个额外的 id 列,所以只需修复这些.

最后我们 运行 pivot_longer 并将其输出转换为 data.frame 表明这与 reshape 的固定输出相同。

out <- reshape(cprefm, dir = "long", varying = names(cprefm), 
  v.names = "value", timevar = "profile", times = names(cprefm))
out <- out[order(out$id), 1:2]
rownames(out) <- NULL

out.piv <- cprefm %>% pivot_longer(1:16, "profile", "rating")

identical(out, as.data.frame(out.piv))
## [1] TRUE

2) pre process w transpose 交替修复before 通过重塑cprefm的转置将其传递给reshape。在那种情况下,我们只需要 select 输出所需的列,而行顺序按需要显示而无需排序。

out2 <- reshape(as.data.frame(t(cprefm)), dir = "long",
  varying = 1:nrow(cprefm), idvar = "profile", v.names = "value", 
  ids = names(cprefm), new.row.names = 1:prod(dim(cprefm)))[3:2]

identical(out2, as.data.frame(out.piv))
## [1] TRUE

3) as.data.frame.table w transpose 转置思想也适用于 as.data.frame.table:

out3 <- with(as.data.frame.table(t(cprefm), responseName = "value"),
  data.frame(profile = as.character(Var1), value))

identical(out3, as.data.frame(out.piv))
## [1] TRUE

这个可以用这样的管道写得很好:

cprefm |>
  t() |>
  as.data.frame.table(responseName = "value") |>
  with(data.frame(profile = as.character(Var1), value))

4) 堆栈 w 转置 和堆栈:

out4 <- with(stack(as.data.frame(t(cprefm))), 
  data.frame(profile = names(cprefm), value = values))

identical(out4, as.data.frame(out.piv))
## [1] TRUE