将变量值转换为列名; "duplicate identifiers for rows" 在 tidyr::spread
Turning variable values into column names; "duplicate identifiers for rows" in tidyr::spread
我正在处理一个混乱的选民文件。考虑以下 tibble
:
library(dplyr)
library(tidyr)
dat <- tibble(
id = factor(c("A","B","C","D","E")),
demographic_info1 = round(rnorm(5),2),
demographic_info2 = round(rnorm(5),2),
election_1 = c(NA,"GN2016","GN2016","SE2016","GN2008"),
election_2 = c(NA,"MT2014","GN2012","GN2016","GN2004"),
election_3 = c(NA,NA,NA,"MT2014","GN2000"),
election_4 = c(NA,NA,NA,"GN2012",NA),
election_5 = c(NA,NA,NA,"MT2010",NA),
)
看起来像:
# A tibble: 5 x 8
id demographic_info1 demographic_info2 election_1 election_2 election_3 election_4 election_5
<fctr> <dbl> <dbl> <chr> <chr> <chr> <chr> <chr>
1 A -1.50 0.81 <NA> <NA> <NA> <NA> <NA>
2 B -1.84 -0.64 GN2016 MT2014 <NA> <NA> <NA>
3 C 1.66 -0.10 GN2016 GN2012 <NA> <NA> <NA>
4 D 0.91 -0.08 SE2016 GN2016 MT2014 GN2012 MT2010
5 E 0.04 -1.15 GN2008 GN2004 GN2000 <NA> <NA>
- 每个
id
都是选民的唯一标识符。
- 两个
demographic_info
列是填充列,只是为了证明我想在对数据进行整形时 保留 这些值。
election_1
到 election_5
列是我感兴趣的内容。数据的结构使得该文件包含某人最近参加的 5 次选举。election_1
是最近的,election_5
是最近的。
请注意,A
人从未投票,而 D
人总是投票。我想做的是将这些列变成许多变量:SE2016
、GN2016
、MT2014
、GN2012
等;即 election_1
到 election_5
中的所有值。我希望这些中的每一个都是 TRUE
或 FALSE
的变量,用于决定那个人是否出现在民意调查中。我试过这段代码:
dat %>% # take data
gather(election, race, election_1:election_5) %>% # gather by election
mutate(temp=TRUE) %>% # make new variable that is all TRUE
select(-election) %>% # drop election variable
spread(race, temp, fill=FALSE) # spread by this all TRUE variable, fill all NAs as FALSE
但是,spread
抛出错误:
Error: Duplicate identifiers for rows (1, 6, 11, 16, 21), (12, 17, 22), (13, 18, 23), (20, 25)
这是因为 race
变量的每个值都有多个条目。在执行 spread
之前,我尝试过 group_by(id)
,但抛出了同样的错误。
我希望结果 tibble
看起来像:
# A tibble: 5 x 11
id demographic_info1 demographic_info2 SE2016 GN2016 MT2014 GN2012 MT2010 GN2008 GN2004 GN2000
<fctr> <dbl> <dbl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl>
1 A -0.91 -0.56 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
2 B 1.24 -1.78 FALSE TRUE TRUE FALSE FALSE FALSE FALSE FALSE
3 C 0.61 0.11 FALSE TRUE FALSE TRUE FALSE FALSE FALSE FALSE
4 D 2.43 -0.53 TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE
5 E -1.40 -1.23 FALSE FALSE FALSE FALSE FALSE TRUE TRUE TRUE
我们可以在 'id' 上使用 group_by
创建一个序列变量,因为 'id' 是重复的,然后在 spread
之后删除它
dat %>%
gather(election, race, election_1:election_5) %>%
mutate(temp=TRUE)%>% group_by(id) %>%
mutate(i1 = row_number()) %>%
select(-election) %>%
spread(race, temp, fill=FALSE) %>%
select(-i1)
问题是 NA
值存在重复条目。我通过只取 unique
行,然后按 id
:
分组,解决了 akrun 答案中重复标识符 和 的多行问题
dat %>%
gather(election, race, election_1:election_5) %>%
mutate(temp=TRUE) %>%
select(-election) %>%
unique() %>% # GET RID OF DUPLICATE NA ENTRIES
group_by(id) %>%
spread(race, temp, fill=FALSE) %>%
select(-`<NA>`)
# A tibble: 5 x 11
# Groups: id [5]
id demographic_info1 demographic_info2 GN2000 GN2004 GN2008 GN2012 GN2016 MT2010 MT2014 SE2016
* <fctr> <dbl> <dbl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl>
1 A -1.19 -0.94 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
2 B 1.41 -0.62 FALSE FALSE FALSE FALSE TRUE FALSE TRUE FALSE
3 C -0.21 1.62 FALSE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
4 D 1.51 0.09 FALSE FALSE FALSE TRUE TRUE TRUE TRUE TRUE
5 E 0.65 -2.09 TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE
tidyr 提供了一些语法来处理这个问题。
# set up
library(dplyr)
library(tidyr)
dat <- tibble(
id = factor(c("A","B","C","D","E")),
demographic_info1 = round(rnorm(5),2),
demographic_info2 = round(rnorm(5),2),
election_1 = c(NA,"GN2016","GN2016","SE2016","GN2008"),
election_2 = c(NA,"MT2014","GN2012","GN2016","GN2004"),
election_3 = c(NA,NA,NA,"MT2014","GN2000"),
election_4 = c(NA,NA,NA,"GN2012",NA),
election_5 = c(NA,NA,NA,"MT2010",NA)
)
我们最终想要的是每个选民 (5) x 选举 (8) 配对的 TRUE
或 FALSE
。当我们将数据收集成长格式时,我们只会看到数据集中存在 的选民 x 选举组合 。
d_votes <- dat %>%
gather("variable", "election", election_1:election_5) %>%
select(-variable) %>%
mutate(voted = TRUE)
d_votes
#> # A tibble: 25 x 5
#> id demographic_info1 demographic_info2 election voted
#> <fctr> <dbl> <dbl> <chr> <lgl>
#> 1 A 0.76 -0.23 <NA> TRUE
#> 2 B -0.80 0.08 GN2016 TRUE
#> 3 C -0.33 1.60 GN2016 TRUE
#> 4 D -0.50 -1.27 SE2016 TRUE
#> 5 E -1.03 0.59 GN2008 TRUE
#> 6 A 0.76 -0.23 <NA> TRUE
#> 7 B -0.80 0.08 MT2014 TRUE
#> 8 C -0.33 1.60 GN2012 TRUE
#> 9 D -0.50 -1.27 GN2016 TRUE
#> 10 E -1.03 0.59 GN2004 TRUE
#> # ... with 15 more rows
count(d_votes, election)
#> # A tibble: 9 x 2
#> election n
#> <chr> <int>
#> 1 GN2000 1
#> 2 GN2004 1
#> 3 GN2008 1
#> 4 GN2012 2
#> 5 GN2016 3
#> 6 MT2010 1
#> 7 MT2014 2
#> 8 SE2016 1
#> 9 <NA> 13
我们需要生成选民和选举的每一个组合。 tidyr 的 expand()
函数根据不同的 columns/vectors 数据创建变量的所有组合。 (它的工作原理类似于基本函数 expand.grid()
,因此名称 expand()
令人回味)。
d_possible_votes <- d_votes %>%
expand(nesting(id, demographic_info1, demographic_info2),
election)
d_possible_votes
#> # A tibble: 40 x 4
#> id demographic_info1 demographic_info2 election
#> <fctr> <dbl> <dbl> <chr>
#> 1 A 0.76 -0.23 GN2000
#> 2 A 0.76 -0.23 GN2004
#> 3 A 0.76 -0.23 GN2008
#> 4 A 0.76 -0.23 GN2012
#> 5 A 0.76 -0.23 GN2016
#> 6 A 0.76 -0.23 MT2010
#> 7 A 0.76 -0.23 MT2014
#> 8 A 0.76 -0.23 SE2016
#> 9 B -0.80 0.08 GN2000
#> 10 B -0.80 0.08 GN2004
#> # ... with 30 more rows
请注意,我们现在有 8 个选择 x 5 个 ID = 40 行。
我们使用 nesting()
函数将每个 (id
, demographic_info1
, demographic_info2
) set/row 视为一个单元;人口统计数据 嵌套 在 id 中。扩展提供了 (id
, demographic_info1
, demographic_info2
) x election
.
的所有 40 种组合
如果我们将观察到的投票加入可能的投票,voted
列将填充 TRUE
或 NA
值。 tidyr 的 replace_na()
函数可以更正那些 NA
值。
d_possible_votes <- d_possible_votes %>%
left_join(d_votes) %>%
replace_na(list(voted = FALSE))
#> Joining, by = c("id", "demographic_info1", "demographic_info2", "election")
d_possible_votes
#> # A tibble: 40 x 5
#> id demographic_info1 demographic_info2 election voted
#> <fctr> <dbl> <dbl> <chr> <lgl>
#> 1 A 0.76 -0.23 GN2000 FALSE
#> 2 A 0.76 -0.23 GN2004 FALSE
#> 3 A 0.76 -0.23 GN2008 FALSE
#> 4 A 0.76 -0.23 GN2012 FALSE
#> 5 A 0.76 -0.23 GN2016 FALSE
#> 6 A 0.76 -0.23 MT2010 FALSE
#> 7 A 0.76 -0.23 MT2014 FALSE
#> 8 A 0.76 -0.23 SE2016 FALSE
#> 9 B -0.80 0.08 GN2000 FALSE
#> 10 B -0.80 0.08 GN2004 FALSE
#> # ... with 30 more rows
现在,我们可以展开选举并获得所需的数据帧。
spread(d_possible_votes, election, voted)
#> # A tibble: 5 x 11
#> id demographic_info1 demographic_info2 GN2000 GN2004 GN2008 GN2012 GN2016 MT2010 MT2014 SE2016
#> * <fctr> <dbl> <dbl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl>
#> 1 A 0.76 -0.23 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
#> 2 B -0.80 0.08 FALSE FALSE FALSE FALSE TRUE FALSE TRUE FALSE
#> 3 C -0.33 1.60 FALSE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
#> 4 D -0.50 -1.27 FALSE FALSE FALSE TRUE TRUE TRUE TRUE TRUE
#> 5 E -1.03 0.59 TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE
这种生成标识符组合、连接实际数据和更正缺失值的模式非常普遍,以至于 tidyr 包含一个函数 complete()
可以同时完成所有这三件事。
d_votes %>%
complete(nesting(id, demographic_info1, demographic_info2),
election, fill = list(voted = FALSE)) %>%
spread(election, voted)
#> # A tibble: 5 x 11
#> id demographic_info1 demographic_info2 GN2000 GN2004 GN2008 GN2012 GN2016 MT2010 MT2014 SE2016
#> * <fctr> <dbl> <dbl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl>
#> 1 A 0.76 -0.23 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
#> 2 B -0.80 0.08 FALSE FALSE FALSE FALSE TRUE FALSE TRUE FALSE
#> 3 C -0.33 1.60 FALSE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
#> 4 D -0.50 -1.27 FALSE FALSE FALSE TRUE TRUE TRUE TRUE TRUE
#> 5 E -1.03 0.59 TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE
我正在处理一个混乱的选民文件。考虑以下 tibble
:
library(dplyr)
library(tidyr)
dat <- tibble(
id = factor(c("A","B","C","D","E")),
demographic_info1 = round(rnorm(5),2),
demographic_info2 = round(rnorm(5),2),
election_1 = c(NA,"GN2016","GN2016","SE2016","GN2008"),
election_2 = c(NA,"MT2014","GN2012","GN2016","GN2004"),
election_3 = c(NA,NA,NA,"MT2014","GN2000"),
election_4 = c(NA,NA,NA,"GN2012",NA),
election_5 = c(NA,NA,NA,"MT2010",NA),
)
看起来像:
# A tibble: 5 x 8
id demographic_info1 demographic_info2 election_1 election_2 election_3 election_4 election_5
<fctr> <dbl> <dbl> <chr> <chr> <chr> <chr> <chr>
1 A -1.50 0.81 <NA> <NA> <NA> <NA> <NA>
2 B -1.84 -0.64 GN2016 MT2014 <NA> <NA> <NA>
3 C 1.66 -0.10 GN2016 GN2012 <NA> <NA> <NA>
4 D 0.91 -0.08 SE2016 GN2016 MT2014 GN2012 MT2010
5 E 0.04 -1.15 GN2008 GN2004 GN2000 <NA> <NA>
- 每个
id
都是选民的唯一标识符。 - 两个
demographic_info
列是填充列,只是为了证明我想在对数据进行整形时 保留 这些值。
election_1
到 election_5
列是我感兴趣的内容。数据的结构使得该文件包含某人最近参加的 5 次选举。election_1
是最近的,election_5
是最近的。
请注意,A
人从未投票,而 D
人总是投票。我想做的是将这些列变成许多变量:SE2016
、GN2016
、MT2014
、GN2012
等;即 election_1
到 election_5
中的所有值。我希望这些中的每一个都是 TRUE
或 FALSE
的变量,用于决定那个人是否出现在民意调查中。我试过这段代码:
dat %>% # take data
gather(election, race, election_1:election_5) %>% # gather by election
mutate(temp=TRUE) %>% # make new variable that is all TRUE
select(-election) %>% # drop election variable
spread(race, temp, fill=FALSE) # spread by this all TRUE variable, fill all NAs as FALSE
但是,spread
抛出错误:
Error: Duplicate identifiers for rows (1, 6, 11, 16, 21), (12, 17, 22), (13, 18, 23), (20, 25)
这是因为 race
变量的每个值都有多个条目。在执行 spread
之前,我尝试过 group_by(id)
,但抛出了同样的错误。
我希望结果 tibble
看起来像:
# A tibble: 5 x 11
id demographic_info1 demographic_info2 SE2016 GN2016 MT2014 GN2012 MT2010 GN2008 GN2004 GN2000
<fctr> <dbl> <dbl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl>
1 A -0.91 -0.56 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
2 B 1.24 -1.78 FALSE TRUE TRUE FALSE FALSE FALSE FALSE FALSE
3 C 0.61 0.11 FALSE TRUE FALSE TRUE FALSE FALSE FALSE FALSE
4 D 2.43 -0.53 TRUE TRUE TRUE TRUE TRUE FALSE FALSE FALSE
5 E -1.40 -1.23 FALSE FALSE FALSE FALSE FALSE TRUE TRUE TRUE
我们可以在 'id' 上使用 group_by
创建一个序列变量,因为 'id' 是重复的,然后在 spread
dat %>%
gather(election, race, election_1:election_5) %>%
mutate(temp=TRUE)%>% group_by(id) %>%
mutate(i1 = row_number()) %>%
select(-election) %>%
spread(race, temp, fill=FALSE) %>%
select(-i1)
问题是 NA
值存在重复条目。我通过只取 unique
行,然后按 id
:
dat %>%
gather(election, race, election_1:election_5) %>%
mutate(temp=TRUE) %>%
select(-election) %>%
unique() %>% # GET RID OF DUPLICATE NA ENTRIES
group_by(id) %>%
spread(race, temp, fill=FALSE) %>%
select(-`<NA>`)
# A tibble: 5 x 11
# Groups: id [5]
id demographic_info1 demographic_info2 GN2000 GN2004 GN2008 GN2012 GN2016 MT2010 MT2014 SE2016
* <fctr> <dbl> <dbl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl>
1 A -1.19 -0.94 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
2 B 1.41 -0.62 FALSE FALSE FALSE FALSE TRUE FALSE TRUE FALSE
3 C -0.21 1.62 FALSE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
4 D 1.51 0.09 FALSE FALSE FALSE TRUE TRUE TRUE TRUE TRUE
5 E 0.65 -2.09 TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE
tidyr 提供了一些语法来处理这个问题。
# set up
library(dplyr)
library(tidyr)
dat <- tibble(
id = factor(c("A","B","C","D","E")),
demographic_info1 = round(rnorm(5),2),
demographic_info2 = round(rnorm(5),2),
election_1 = c(NA,"GN2016","GN2016","SE2016","GN2008"),
election_2 = c(NA,"MT2014","GN2012","GN2016","GN2004"),
election_3 = c(NA,NA,NA,"MT2014","GN2000"),
election_4 = c(NA,NA,NA,"GN2012",NA),
election_5 = c(NA,NA,NA,"MT2010",NA)
)
我们最终想要的是每个选民 (5) x 选举 (8) 配对的 TRUE
或 FALSE
。当我们将数据收集成长格式时,我们只会看到数据集中存在 的选民 x 选举组合 。
d_votes <- dat %>%
gather("variable", "election", election_1:election_5) %>%
select(-variable) %>%
mutate(voted = TRUE)
d_votes
#> # A tibble: 25 x 5
#> id demographic_info1 demographic_info2 election voted
#> <fctr> <dbl> <dbl> <chr> <lgl>
#> 1 A 0.76 -0.23 <NA> TRUE
#> 2 B -0.80 0.08 GN2016 TRUE
#> 3 C -0.33 1.60 GN2016 TRUE
#> 4 D -0.50 -1.27 SE2016 TRUE
#> 5 E -1.03 0.59 GN2008 TRUE
#> 6 A 0.76 -0.23 <NA> TRUE
#> 7 B -0.80 0.08 MT2014 TRUE
#> 8 C -0.33 1.60 GN2012 TRUE
#> 9 D -0.50 -1.27 GN2016 TRUE
#> 10 E -1.03 0.59 GN2004 TRUE
#> # ... with 15 more rows
count(d_votes, election)
#> # A tibble: 9 x 2
#> election n
#> <chr> <int>
#> 1 GN2000 1
#> 2 GN2004 1
#> 3 GN2008 1
#> 4 GN2012 2
#> 5 GN2016 3
#> 6 MT2010 1
#> 7 MT2014 2
#> 8 SE2016 1
#> 9 <NA> 13
我们需要生成选民和选举的每一个组合。 tidyr 的 expand()
函数根据不同的 columns/vectors 数据创建变量的所有组合。 (它的工作原理类似于基本函数 expand.grid()
,因此名称 expand()
令人回味)。
d_possible_votes <- d_votes %>%
expand(nesting(id, demographic_info1, demographic_info2),
election)
d_possible_votes
#> # A tibble: 40 x 4
#> id demographic_info1 demographic_info2 election
#> <fctr> <dbl> <dbl> <chr>
#> 1 A 0.76 -0.23 GN2000
#> 2 A 0.76 -0.23 GN2004
#> 3 A 0.76 -0.23 GN2008
#> 4 A 0.76 -0.23 GN2012
#> 5 A 0.76 -0.23 GN2016
#> 6 A 0.76 -0.23 MT2010
#> 7 A 0.76 -0.23 MT2014
#> 8 A 0.76 -0.23 SE2016
#> 9 B -0.80 0.08 GN2000
#> 10 B -0.80 0.08 GN2004
#> # ... with 30 more rows
请注意,我们现在有 8 个选择 x 5 个 ID = 40 行。
我们使用 nesting()
函数将每个 (id
, demographic_info1
, demographic_info2
) set/row 视为一个单元;人口统计数据 嵌套 在 id 中。扩展提供了 (id
, demographic_info1
, demographic_info2
) x election
.
如果我们将观察到的投票加入可能的投票,voted
列将填充 TRUE
或 NA
值。 tidyr 的 replace_na()
函数可以更正那些 NA
值。
d_possible_votes <- d_possible_votes %>%
left_join(d_votes) %>%
replace_na(list(voted = FALSE))
#> Joining, by = c("id", "demographic_info1", "demographic_info2", "election")
d_possible_votes
#> # A tibble: 40 x 5
#> id demographic_info1 demographic_info2 election voted
#> <fctr> <dbl> <dbl> <chr> <lgl>
#> 1 A 0.76 -0.23 GN2000 FALSE
#> 2 A 0.76 -0.23 GN2004 FALSE
#> 3 A 0.76 -0.23 GN2008 FALSE
#> 4 A 0.76 -0.23 GN2012 FALSE
#> 5 A 0.76 -0.23 GN2016 FALSE
#> 6 A 0.76 -0.23 MT2010 FALSE
#> 7 A 0.76 -0.23 MT2014 FALSE
#> 8 A 0.76 -0.23 SE2016 FALSE
#> 9 B -0.80 0.08 GN2000 FALSE
#> 10 B -0.80 0.08 GN2004 FALSE
#> # ... with 30 more rows
现在,我们可以展开选举并获得所需的数据帧。
spread(d_possible_votes, election, voted)
#> # A tibble: 5 x 11
#> id demographic_info1 demographic_info2 GN2000 GN2004 GN2008 GN2012 GN2016 MT2010 MT2014 SE2016
#> * <fctr> <dbl> <dbl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl>
#> 1 A 0.76 -0.23 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
#> 2 B -0.80 0.08 FALSE FALSE FALSE FALSE TRUE FALSE TRUE FALSE
#> 3 C -0.33 1.60 FALSE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
#> 4 D -0.50 -1.27 FALSE FALSE FALSE TRUE TRUE TRUE TRUE TRUE
#> 5 E -1.03 0.59 TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE
这种生成标识符组合、连接实际数据和更正缺失值的模式非常普遍,以至于 tidyr 包含一个函数 complete()
可以同时完成所有这三件事。
d_votes %>%
complete(nesting(id, demographic_info1, demographic_info2),
election, fill = list(voted = FALSE)) %>%
spread(election, voted)
#> # A tibble: 5 x 11
#> id demographic_info1 demographic_info2 GN2000 GN2004 GN2008 GN2012 GN2016 MT2010 MT2014 SE2016
#> * <fctr> <dbl> <dbl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl> <lgl>
#> 1 A 0.76 -0.23 FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE
#> 2 B -0.80 0.08 FALSE FALSE FALSE FALSE TRUE FALSE TRUE FALSE
#> 3 C -0.33 1.60 FALSE FALSE FALSE TRUE TRUE FALSE FALSE FALSE
#> 4 D -0.50 -1.27 FALSE FALSE FALSE TRUE TRUE TRUE TRUE TRUE
#> 5 E -1.03 0.59 TRUE TRUE TRUE FALSE FALSE FALSE FALSE FALSE