从长格式到宽格式,新生成的列灵活地反映值出现的顺序
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
我正在尝试将我的数据集从长格式重新格式化为宽格式,但尽管这是讨论最多的主题之一,但我找不到适合我的案例的解决方案,也无法从其他人使用的方法中进行概括。
我的数据是长格式,其中每个 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()
(灵感来自
理想情况下,一个解决方案可以解决我提供的两个数据版本。它基本上只需要不知道每个 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