首页 > 解决方案 > 当每列需要分成3列以上时,如何从宽数据到长数据

问题描述

[对此还是新手,如果我需要提供更多信息来帮助解决我的问题,请告诉我]

试图帮助实验室成员进行一些数据分析,但数据中的列名混合了几个变量。

在他的数据中,每一行代表一个平均值。每列命名为 mean.xyz,其中 x、y 和 z 指的是不同变量的不同值。我们需要做的是将每个列名拆分为其复合部分,并为每个部分创建单独的列。

举一个更具体的例子,如果这是我们提供的数据:

messy <- tibble(
  id = c('P1', 'P2', 'P3'),
  value.neutral.up = c(1.2, 1.3, 1.2),
  value.neutral.down = c(2.1, 3.1, 2.1),
  value.valid.up = c(1.2, 1.3, 1.2),
  value.valid.down = c(2.1, 3.1, 2.1),
  value.invalid.up = c(1.2, 1.3, 1.2),
  value.invalid.down = c(2.1, 3.1, 2.1)
)
messy
# A tibble: 3 x 7
  id    value.neutral.up value.neutral.down value.valid.up value.valid.down value.invalid.up value.invalid.down
  <chr>            <dbl>              <dbl>          <dbl>            <dbl>            <dbl>              <dbl>
1 P1                 1.2                2.1            1.2              2.1              1.2                2.1
2 P2                 1.3                3.1            1.3              3.1              1.3                3.1
3 P3                 1.2                2.1            1.2              2.1              1.2                2.1

值是指我们要提取的数值,中性/有效/无效和上/下是指两个预测变量的水平。

考虑到这一点,我们的最终目标如下所示:

tidy <- tibble(
  id = c( rep('P1', 6), rep('P2', 6), rep('P3', 6)),
  cue = rep(c('neutral', 'valid', 'invalid'),6),
  direction = rep(c('up', 'down'), 9),
  value = rep(c(1.2, 1.3, 1.4, 2.1, 3.1, 4.1), 3) 
)

tidy
# A tibble: 18 x 4
   id    cue     direction value
   <chr> <chr>   <chr>     <dbl>
 1 P1    neutral up          1.2
 2 P1    valid   down        1.3
 3 P1    invalid up          1.4
 4 P1    neutral down        2.1
 5 P1    valid   up          3.1
 6 P1    invalid down        4.1
 7 P2    neutral up          1.2
 8 P2    valid   down        1.3
 9 P2    invalid up          1.4
10 P2    neutral down        2.1
11 P2    valid   up          3.1
12 P2    invalid down        4.1
13 P3    neutral up          1.2
14 P3    valid   down        1.3
15 P3    invalid up          1.4
16 P3    neutral down        2.1
17 P3    valid   up          3.1
18 P3    invalid down        4.1

我以前使用过 reshape2::gather() 来解决这类问题,但仅限于列名没有复合多个变量名的情况。也就是说,如果列是 value.neutral、value.valid 等,那很好,但我不知道如何处理额外的 .up/down 位。

有关如何处理此问题的任何建议?即使有人可以帮助我更好地表达这个问题(以可搜索的术语),我也会很感激。

谢谢各位!

标签: rtidyr

解决方案


library(dplyr)
library(reshape2)
library(tidyr)

reshape2::melt(messy,id.vars="id") %>%
    tidyr::separate("variable",into = c("drop","cue","direction")) %>%
    select(-drop)
   id     cue direction value
1  P1 neutral        up   1.2
2  P2 neutral        up   1.3
3  P3 neutral        up   1.2
4  P1 neutral      down   2.1
5  P2 neutral      down   3.1
6  P3 neutral      down   2.1
7  P1   valid        up   1.2
8  P2   valid        up   1.3
9  P3   valid        up   1.2
10 P1   valid      down   2.1
11 P2   valid      down   3.1
12 P3   valid      down   2.1
13 P1 invalid        up   1.2
14 P2 invalid        up   1.3
15 P3 invalid        up   1.2
16 P1 invalid      down   2.1
17 P2 invalid      down   3.1
18 P3 invalid      down   2.1

推荐阅读