将不同的观察结果重塑为宽
reshape different observations to wide
我有这样的数据:
dat <- data.frame(id=c(1,1,1,2,2,2),
v1=factor(c("name","sex","age",
"name","sex","age")),
v2=factor(c("a","m","50","b","f","40")))
>dat
id v1 v2
1 1 name a
2 1 sex m
3 1 age 50
4 2 name b
5 2 sex f
6 2 age 40
如何将其重新整形为宽 table,其中每个 ID 只有一行。像这样:
id name sex age
1 a m 50
2 b f 40
在下一步中,假设我的数据如下所示,即第二个 id
缺少 name
dat2 <- data.frame(id=c(1,1,1,2,2),
v1=factor(c("name","sex","age",
"sex","age")),
v2=factor(c("a","m","50","f","40")))
table 应该如下所示(包含 NA
):
id name sex age
1 a m 50
2 NA f 40
并不是说我的真实数据集可能包含多种因素和数字变量。此外,每个 id 的条目数可能会有很大差异。
在接下来的情况下,V1
可能会出现多次,像这样
dat3 <- data.frame(id=c(1,1,1,2,2),
v1=factor(c("value","value","obs",
"value", "obs")),
v2=factor(c("5","3","5","6","8")))
table 应该看起来像这样
id value1 value2 obs
1 5 3 5
2 6 NA 8
我还希望看到一个解决方案,当每个 id 有多个 value
时,计算平均值(或最大值、最小值、..),就像这样
id value obs
1 4 5 # mean(c(3,5)==4
2 6 8
谢谢
让我们使用 tidyr
和 dplyr
:
library(tidyr)
library(dplyr)
第一个问题:
spread(dat, v1, v2)
id age name sex
1 1 50 a m
2 2 40 b f
第二个问题是相同的 - 数据丢失时传播自动使用 NA:
spread(dat2, v1, v2)
id age name sex
1 1 50 a m
2 2 40 <NA> f
第三题,我们先用dplyr总结,然后展开,把v2转成numeric后:
dat3 %>% mutate(v2 = as.numeric(as.character(v2))) %>%
group_by(id, v1) %>%
summarise(mean = mean(v2)) %>%
spread(v1, mean)
Source: local data frame [2 x 3]
id obs value
1 1 5 4
2 2 8 6
对于更宽的版本,我们可以使用 unite
:
dat3 %>% group_by(id, v1) %>%
mutate(v2 = as.numeric(as.character(v2)), id2=row_number()) %>%
unite(v3, c(v1,id2)) %>%
spread(v3, v2)
Source: local data frame [2 x 4]
id obs_1 value_1 value_2
1 1 5 5 3
2 2 8 6 NA
我有这样的数据:
dat <- data.frame(id=c(1,1,1,2,2,2),
v1=factor(c("name","sex","age",
"name","sex","age")),
v2=factor(c("a","m","50","b","f","40")))
>dat
id v1 v2
1 1 name a
2 1 sex m
3 1 age 50
4 2 name b
5 2 sex f
6 2 age 40
如何将其重新整形为宽 table,其中每个 ID 只有一行。像这样:
id name sex age
1 a m 50
2 b f 40
在下一步中,假设我的数据如下所示,即第二个 id
name
dat2 <- data.frame(id=c(1,1,1,2,2),
v1=factor(c("name","sex","age",
"sex","age")),
v2=factor(c("a","m","50","f","40")))
table 应该如下所示(包含 NA
):
id name sex age
1 a m 50
2 NA f 40
并不是说我的真实数据集可能包含多种因素和数字变量。此外,每个 id 的条目数可能会有很大差异。
在接下来的情况下,V1
可能会出现多次,像这样
dat3 <- data.frame(id=c(1,1,1,2,2),
v1=factor(c("value","value","obs",
"value", "obs")),
v2=factor(c("5","3","5","6","8")))
table 应该看起来像这样
id value1 value2 obs
1 5 3 5
2 6 NA 8
我还希望看到一个解决方案,当每个 id 有多个 value
时,计算平均值(或最大值、最小值、..),就像这样
id value obs
1 4 5 # mean(c(3,5)==4
2 6 8
谢谢
让我们使用 tidyr
和 dplyr
:
library(tidyr)
library(dplyr)
第一个问题:
spread(dat, v1, v2)
id age name sex
1 1 50 a m
2 2 40 b f
第二个问题是相同的 - 数据丢失时传播自动使用 NA:
spread(dat2, v1, v2)
id age name sex
1 1 50 a m
2 2 40 <NA> f
第三题,我们先用dplyr总结,然后展开,把v2转成numeric后:
dat3 %>% mutate(v2 = as.numeric(as.character(v2))) %>%
group_by(id, v1) %>%
summarise(mean = mean(v2)) %>%
spread(v1, mean)
Source: local data frame [2 x 3]
id obs value
1 1 5 4
2 2 8 6
对于更宽的版本,我们可以使用 unite
:
dat3 %>% group_by(id, v1) %>%
mutate(v2 = as.numeric(as.character(v2)), id2=row_number()) %>%
unite(v3, c(v1,id2)) %>%
spread(v3, v2)
Source: local data frame [2 x 4]
id obs_1 value_1 value_2
1 1 5 5 3
2 2 8 6 NA