【问题标题】:How to reproduce the result of pivot_longer with reshape in base R?如何在基础 R 中通过 reshape 重现 pivot_longer 的结果?
【发布时间】:2021-12-13 00:47:53
【问题描述】:

考虑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

我无法用 reshape 函数重现这个:

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 相同。

【问题讨论】:

    标签: r reshape


    【解决方案1】:

    1) 后期处理问题中的 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) 预处理 w 转置 交替修复它之前 通过重塑 cprefm 的转置来重塑它。在这种情况下,我们只需要选择所需的列,而无需排序即可根据需要显示行顺序。

    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
    

    【讨论】:

    • 这很全面!
    【解决方案2】:

    如果不使用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
    

    【讨论】:

      【解决方案3】:

      对于base 中的完整支点,我会使用stack,无需编辑以使其与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
      # ...
      

      【讨论】:

      • 但是结果是有序的(profile1, profile1, profile1 ...)
      • 数据排序非常简单。
      • pivot_longer 中,结果是profile1profile2profile3...(14155...)。 reshapestack 对值进行排序。
      • 好的,所以为了清楚起见,您想要一个以特定方式排序的结果,但没有任何类型的 id 列或其他顺序证据,这样如果它变得无序,就没有通知或纠正的方法?
      • 如果profile 列与pivot_longer 相同,那很好。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-11-06
      • 1970-01-01
      • 1970-01-01
      • 2021-05-13
      • 2013-07-15
      • 1970-01-01
      • 2021-03-27
      相关资源
      最近更新 更多