从R

时间:2016-10-06 14:52:31

标签: r data-manipulation

为了简单起见,假设我有一个国家/地区级别的数据集,其中列出了从政府获得援助的组织,该项目的金额以及项目类型。数据框架每年为10个组织提供“空间”,但并非每个政府每年都对这么多组织提供补贴,因此存在很多空白。此外,他们不遵循任何顺序:一个组织可以在第一个位置一年,第二年可以在第二个位置编码。数据如下所示:

> State  Year  Org1 Aid1 Proj1   Org2 Aid2 Proj2   Org3 Aid3 Proj3   Org4 Aid4 Proj4 ...
  Italy  2000  A    1000 Arts    B    500  Arts    C    300  Social
  Italy  2001  B    700  Social  A    1000 Envir
  Italy  2002  A    1000 Arts    C    300  Envir
  UK     2000
  UK     2001  Z    2000 Social
  UK     2002  Z    2000 Social
  ...

我正在尝试将其转换为二元数据,如下所示:

> State   Org   Year   Aid   Proj
  Italy   A     2000   1000  Arts
  Italy   A     2001   1000  Envir
  Italy   A     2002   1000  Arts
  Italy   B     2000   500   Arts
  Italy   B     2001   700   Social
  Italy   C     2000   300   Social
  Italy   C     2002   300   Envir
  UK      Z     2001   2000  Social
  ... 

我正在使用R,我能找到的最好的方法是构建一个预定义的可能的二元组 - 使用像expand.grid(unique(State), unique(Org))这样的东西 - 然后循环遍历数据,找到相应的列并填充数据框。但我不认为这是最有效的方法,所以我想知道是否会有更好的方法。我考虑过dplyrreshape,但无法找到解决方案。

我知道这是一个反复出现的问题,但无法真正找到答案。最相似的问题是this one,但它并不完全相同。

提前多多感谢。

1 个答案:

答案 0 :(得分:1)

由于您没有使用dput,我会尝试制作一些类似于您的数据:

dat = data.frame(State = rep(c("Italy", "UK"), 3),
                 Year = rep(c(2014, 2015, 2016), 2),
                 Org1 = letters[1:6],
                 Aid1 = sample(800:1000, 6),
                 Proj1 = rep(c("A", "B"), 3),
                 Org2 = letters[7:12],
                 Aid2 = sample(600:700, 6),
                 Proj2 = rep(c("C", "D"), 3),
                 stringsAsFactors = FALSE)

dat

#   State Year Org1 Aid1 Proj1 Org2 Aid2 Proj2
# 1 Italy 2014    a  910     A    g  658     C
# 2    UK 2015    b  926     B    h  681     D
# 3 Italy 2016    c  834     A    i  625     C
# 4    UK 2014    d  858     B    j  620     D
# 5 Italy 2015    e  831     A    k  650     C
# 6    UK 2016    f  821     B    l  687     D

接下来我gather数据,然后使用extract制作2个新列,然后再将其全部展开:

library(tidyr)
library(dplyr)

dat %>%
  gather(key, value, -c(State, Year)) %>%
  extract(key, into = c("key", "num"), "([A-Za-z]+)([0-9]+)") %>% 
  spread(key, value) %>% 
  select(-num)

#    State Year Aid Org Proj
# 1  Italy 2014 910   a    A
# 2  Italy 2014 658   g    C
# 3  Italy 2015 831   e    A
# 4  Italy 2015 650   k    C
# 5  Italy 2016 834   c    A
# 6  Italy 2016 625   i    C
# 7     UK 2014 858   d    B
# 8     UK 2014 620   j    D
# 9     UK 2015 926   b    B
# 10    UK 2015 681   h    D
# 11    UK 2016 821   f    B
# 12    UK 2016 687   l    D

这是所需的输出吗?