根据 R 中第二列的条件为列中的每个唯一值创建虚拟变量
Create dummy variables for every unique value in a column based on a condition from a second column in R
我有一个数据框,看起来有点像这样,有更多的行和列:
> df <- data.frame(country = c ("Australia","Australia","Australia","Angola","Angola","Angola","US","US","US"), year=c("1945","1946","1947"), leader = c("David", "NA", "NA", "NA","Henry","NA","Tom","NA","Chris"), natural.death = c(0,NA,NA,NA,1,NA,1,NA,0),gdp.growth.rate=c(1,4,3,5,6,1,5,7,9))
> df
country year leader natural.death gdp.growth.rate
1 Australia 1945 David 0 1
2 Australia 1946 NA NA 4
3 Australia 1947 NA NA 3
4 Angola 1945 NA NA 5
5 Angola 1946 Henry 1 6
6 Angola 1947 NA NA 1
7 US 1945 Tom 1 5
8 US 1946 NA NA 7
9 US 1947 Chris 0 9
我正在尝试添加 x 个新列,其中 x 对应于满足领导者死亡条件 (natural.death==1) 的唯一领导者(列领导者)的数量。在这个 df 的情况下,我希望为 Henry 和 Tom 获得 2 个新列,值为 0,0,0,0,1,0,0,0,0 和 0,0,0,0,0 ,0,1,0,0,分别。根据 natural.death 中显示的数据顺序,我最好使用名为 id1 和 id2 的两个新列。我需要创建 69 个新列,因为有 69 位领导人去世了,所以我正在寻找一种非手动方法来处理这个问题。
我已经尝试过循环,if、for、unique、mtabulate、dcast、dummies,但不幸的是我无法得到任何工作。
我希望得到:
> df <- data.frame(country = c ("Australia","Australia","Australia","Angola","Angola","Angola","US","US","US"), year=c("1945","1946","1947"), leader = c("David", "NA", "NA", "NA","Henry","NA","Tom","NA","Chris"), natural.death = c(0,NA,NA,NA,1,NA,1,NA,0),gdp.growth.rate=c(1,4,3,5,6,1,5,7,9),
+ id1=c(0,0,0,0,1,0,0,0,0),id2=c(0,0,0,0,0,0,1,0,0))
> df
country year leader natural.death gdp.growth.rate id1 id2
1 Australia 1945 David 0 1 0 0
2 Australia 1946 NA NA 4 0 0
3 Australia 1947 NA NA 3 0 0
4 Angola 1945 NA NA 5 0 0
5 Angola 1946 Henry 1 6 1 0
6 Angola 1947 NA NA 1 0 0
7 US 1945 Tom 1 5 0 1
8 US 1946 NA NA 7 0 0
9 US 1947 Chris 0 9 0 0
这是一个粗略的方法
df <- data.frame(country = c ("Australia","Australia","Australia","Angola","Angola","Angola","US","US","US"), year=c("1945","1946","1947"), leader = c("David", "NA", "NA", "NA","Henry","NA","Tom","NA","Chris"), natural.death = c(0,NA,NA,NA,1,NA,1,NA,0),gdp.growth.rate=c(1,4,3,5,6,1,5,7,9))
tmp=which(df$natural.death==1) #index of deaths
lng=length(tmp) #number of deaths
#create matrix with zeros and lng columns, append to df
df=cbind(df,data.frame(matrix(0,nrow=nrow(df),ncol=lng)))
#change the newly added column names
colnames(df)[(ncol(df)-lng+1):ncol(df)]=paste0("id",1:lng)
for (i in 1:lng) { #loop over new columns
df[tmp[i],paste0("id",i)]=1 #at index i of death and column id+i set df to 1
}
country year leader natural.death gdp.growth.rate id1 id2
1 Australia 1945 David 0 1 0 0
2 Australia 1946 NA NA 4 0 0
3 Australia 1947 NA NA 3 0 0
4 Angola 1945 NA NA 5 0 0
5 Angola 1946 Henry 1 6 1 0
6 Angola 1947 NA NA 1 0 0
7 US 1945 Tom 1 5 0 1
8 US 1946 NA NA 7 0 0
9 US 1947 Chris 0 9 0 0
以及 tidyverse 的方法。
library(tidyverse)
df %>%
mutate(id = ifelse(natural.death == 1, 1, 0),
id = ifelse(is.na(id), 0, id),
tmp = cumsum(id)) %>%
pivot_wider(names_prefix = "id",
names_from = tmp,
values_from = id,
values_fill = list(id = 0)) %>%
select(-id0)
country year leader natural.death gdp.growth.rate id1 id2
<fct> <fct> <fct> <dbl> <dbl> <dbl> <dbl>
1 Australia 1945 David 0 1 0 0
2 Australia 1946 NA NA 4 0 0
3 Australia 1947 NA NA 3 0 0
4 Angola 1945 NA NA 5 0 0
5 Angola 1946 Henry 1 6 1 0
6 Angola 1947 NA NA 1 0 0
7 US 1945 Tom 1 5 0 1
8 US 1946 NA NA 7 0 0
9 US 1947 Chris 0 9 0 0
我有一个数据框,看起来有点像这样,有更多的行和列:
> df <- data.frame(country = c ("Australia","Australia","Australia","Angola","Angola","Angola","US","US","US"), year=c("1945","1946","1947"), leader = c("David", "NA", "NA", "NA","Henry","NA","Tom","NA","Chris"), natural.death = c(0,NA,NA,NA,1,NA,1,NA,0),gdp.growth.rate=c(1,4,3,5,6,1,5,7,9))
> df
country year leader natural.death gdp.growth.rate
1 Australia 1945 David 0 1
2 Australia 1946 NA NA 4
3 Australia 1947 NA NA 3
4 Angola 1945 NA NA 5
5 Angola 1946 Henry 1 6
6 Angola 1947 NA NA 1
7 US 1945 Tom 1 5
8 US 1946 NA NA 7
9 US 1947 Chris 0 9
我正在尝试添加 x 个新列,其中 x 对应于满足领导者死亡条件 (natural.death==1) 的唯一领导者(列领导者)的数量。在这个 df 的情况下,我希望为 Henry 和 Tom 获得 2 个新列,值为 0,0,0,0,1,0,0,0,0 和 0,0,0,0,0 ,0,1,0,0,分别。根据 natural.death 中显示的数据顺序,我最好使用名为 id1 和 id2 的两个新列。我需要创建 69 个新列,因为有 69 位领导人去世了,所以我正在寻找一种非手动方法来处理这个问题。
我已经尝试过循环,if、for、unique、mtabulate、dcast、dummies,但不幸的是我无法得到任何工作。
我希望得到:
> df <- data.frame(country = c ("Australia","Australia","Australia","Angola","Angola","Angola","US","US","US"), year=c("1945","1946","1947"), leader = c("David", "NA", "NA", "NA","Henry","NA","Tom","NA","Chris"), natural.death = c(0,NA,NA,NA,1,NA,1,NA,0),gdp.growth.rate=c(1,4,3,5,6,1,5,7,9),
+ id1=c(0,0,0,0,1,0,0,0,0),id2=c(0,0,0,0,0,0,1,0,0))
> df
country year leader natural.death gdp.growth.rate id1 id2
1 Australia 1945 David 0 1 0 0
2 Australia 1946 NA NA 4 0 0
3 Australia 1947 NA NA 3 0 0
4 Angola 1945 NA NA 5 0 0
5 Angola 1946 Henry 1 6 1 0
6 Angola 1947 NA NA 1 0 0
7 US 1945 Tom 1 5 0 1
8 US 1946 NA NA 7 0 0
9 US 1947 Chris 0 9 0 0
这是一个粗略的方法
df <- data.frame(country = c ("Australia","Australia","Australia","Angola","Angola","Angola","US","US","US"), year=c("1945","1946","1947"), leader = c("David", "NA", "NA", "NA","Henry","NA","Tom","NA","Chris"), natural.death = c(0,NA,NA,NA,1,NA,1,NA,0),gdp.growth.rate=c(1,4,3,5,6,1,5,7,9))
tmp=which(df$natural.death==1) #index of deaths
lng=length(tmp) #number of deaths
#create matrix with zeros and lng columns, append to df
df=cbind(df,data.frame(matrix(0,nrow=nrow(df),ncol=lng)))
#change the newly added column names
colnames(df)[(ncol(df)-lng+1):ncol(df)]=paste0("id",1:lng)
for (i in 1:lng) { #loop over new columns
df[tmp[i],paste0("id",i)]=1 #at index i of death and column id+i set df to 1
}
country year leader natural.death gdp.growth.rate id1 id2
1 Australia 1945 David 0 1 0 0
2 Australia 1946 NA NA 4 0 0
3 Australia 1947 NA NA 3 0 0
4 Angola 1945 NA NA 5 0 0
5 Angola 1946 Henry 1 6 1 0
6 Angola 1947 NA NA 1 0 0
7 US 1945 Tom 1 5 0 1
8 US 1946 NA NA 7 0 0
9 US 1947 Chris 0 9 0 0
以及 tidyverse 的方法。
library(tidyverse)
df %>%
mutate(id = ifelse(natural.death == 1, 1, 0),
id = ifelse(is.na(id), 0, id),
tmp = cumsum(id)) %>%
pivot_wider(names_prefix = "id",
names_from = tmp,
values_from = id,
values_fill = list(id = 0)) %>%
select(-id0)
country year leader natural.death gdp.growth.rate id1 id2
<fct> <fct> <fct> <dbl> <dbl> <dbl> <dbl>
1 Australia 1945 David 0 1 0 0
2 Australia 1946 NA NA 4 0 0
3 Australia 1947 NA NA 3 0 0
4 Angola 1945 NA NA 5 0 0
5 Angola 1946 Henry 1 6 1 0
6 Angola 1947 NA NA 1 0 0
7 US 1945 Tom 1 5 0 1
8 US 1946 NA NA 7 0 0
9 US 1947 Chris 0 9 0 0