从长格式到宽格式,新生成的列灵活地反映值出现的顺序

From long to wide format, where new generated columns flexibly reflect order of value occurrence

我正在尝试将我的数据集从长格式重新格式化为宽格式,但尽管这是讨论最多的主题之一,但我找不到适合我的案例的解决方案,也无法从其他人使用的方法中进行概括。

我的数据是长格式,其中每个 ID 有不同的行数(相对于其他 ID)。我想转换为宽格式,其中每个 ID 有一行,数据由列表示反映每个值在每个 ID 中出现的顺序的后缀。

举例说明:

请注意,两种格式之间的 NA 值不一定对应。在长格式中,NAs 只是从数据中丢失了;但在宽格式中,NA 出现在 that id 的值不足以填充其他 ID 可能具有的变量 x 值的数量的地方。

我的数据

在现实生活中,我的数据有不止一个变量,它可能有两个版本之一:

版本 1 :: 对于每个 ID,值出现在变量的同一行

## reproducible data
set.seed(125)
runs_per_id <- sample(5:9, 4, replace = TRUE)
id <- rep(1:4, times = runs_per_id)

set.seed(300)
is_value <- sample (c(0, 1), size = length(id), replace = TRUE)
x <- is_value
x[which(as.logical(is_value))] <- sample(1:100, size = sum(x))
y <- is_value
y[which(as.logical(is_value))] <- sample(1:100, size = sum(y))
z <- is_value
z[which(as.logical(is_value))] <- sample(1:100, size = sum(z))
d <- as.data.frame(cbind(id, x, y, z))
d[d == 0] <- NA

d

#    id  x  y  z
# 1   1 38 63 61
# 2   1 17 27 76
# 3   1 32 81 89
# 4   1 NA NA NA
# 5   1 75  2 53
# 6   1 NA NA NA
# 7   2 NA NA NA
# 8   2 40 75  4
# 9   2 NA NA NA
# 10  2 NA NA NA
# 11  2 28 47 70
# 12  2 NA NA NA
# 13  2 71 67 33
# 14  3 NA NA NA
# 15  3 95 26 82
# 16  3 NA NA NA
# 17  3 41  7 99
# 18  3 97  8 68
# 19  4 NA NA NA
# 20  4 NA NA NA
# 21  4 93 38 58
# 22  4 NA NA NA
# 23  4 NA NA NA

版本 2 :: 对于每个 ID,值不一定出现在变量的同一行

## reproducible data based on generating d from above
set.seed(12)
d2 <- data.frame(replicate(3, sample(0:1,length(id),rep=TRUE)))
d2[d2 != 0] <- sample(1:100, size = sum(d2 != 0))
d2[d2 == 0] <- NA
colnames(d2) <- c("x", "y", "z")
d2 <- as.data.frame(cbind(id, d2))

d2

##    id  x  y  z
## 1   1 18 28  5
## 2   1 85 93 22
## 3   1 55 59 NA
## 4   1 NA NA 67
## 5   1 NA 15 77
## 6   1 58 NA NA
## 7   2 NA  7 NA
## 8   2 NA NA 91
## 9   2 88 14 NA
## 10  2 13 NA NA
## 11  2 32 NA NA
## 12  2 NA 80 71
## 13  2 40 74 69
## 14  3 NA NA NA
## 15  3 96 NA 76
## 16  3 NA NA NA
## 17  3 73 66 NA
## 18  3 52 NA NA
## 19  4 56 12 16
## 20  4 53 NA NA
## 21  4 NA 42 84
## 22  4 39 99 NA
## 23  4 NA 37 NA

我正在寻找的输出

版本 1 的数据

版本 2 的数据

正在尝试解决这个问题

我已经使用了 dplyr::spread() 甚至新的实验性 pivot_wider()(灵感来自 ),但无法达到 number 沿变量出现的值,将在列名称中表示。

理想情况下,一个解决方案可以解决我提供的两个数据版本。它基本上只需要不知道每个 id 在每列中具有的值的数量,并让数据决定......我认为这是一个简单的问题,但我无法解决这个问题。

谢谢!!!

以下是根据@A.Suliman评论的解决方案。

library(tidyr)
library(dplyr)

d %>% 
  # Combine all values besides id in one column
  gather(key, value, -id) %>% 
  # Filter rows without a value
  filter(!is.na(value)) %>% 
  group_by(id, key) %>% 
  # Create a new key variable numbering the key for each id
  mutate(key_new = paste0(key, seq_len(n()))) %>% 
  ungroup() %>% 
  select(-key) %>% 
  # Spread the data with the new key
  spread(key_new, value)

# A tibble: 4 x 13
#      id    x1    x2    x3    x4    y1    y2    y3    y4    z1    z2    z3    z4
#   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
# 1     1    38    17    32    75    63    27    81     2    61    76    89    53
# 2     2    40    28    71    NA    75    47    67    NA     4    70    33    NA
# 3     3    95    41    97    NA    26     7     8    NA    82    99    68    NA
# 4     4    93    NA    NA    NA    38    NA    NA    NA    58    NA    NA    NA

对于 d2 而不是 d 它给出:

# A tibble: 4 x 13
#      id    x1    x2    x3    x4    y1    y2    y3    y4    z1    z2    z3    z4
#   <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int>
# 1     1    18    85    55    58    28    93    59    15     5    22    67    77
# 2     2    88    13    32    40     7    14    80    74    91    71    69    NA
# 3     3    96    73    52    NA    66    NA    NA    NA    76    NA    NA    NA
# 4     4    56    53    39    NA    12    42    99    37    16    84    NA    NA