根据R

时间:2019-12-02 09:17:18

标签: r dataframe multiple-columns dummy-variable

我有一个看起来像这样的数据框,其中有更多的行和列:

> 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个领导者阵亡,所以我正在寻找一种非手动方法来处理此问题。

我已经尝试过循环,例如,对于唯一的,列表化的,dcast的,虚拟的,但是不幸的是我什么都做不了。

我希望得到:

> 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

2 个答案:

答案 0 :(得分:1)

这是执行此操作的粗略方法

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

答案 1 :(得分:1)

还有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