合并R中的类似观察

时间:2014-10-11 23:31:34

标签: r data-manipulation

我试图用R来做一些数据管理。

我有一个数据框,作为多个变量(+200列)和许多观察(+10,000行)。有大量缺失的数据,以及重复或未完成的观察。 一个观察应该等于一个人(1行= 1个独特的人)

这是数据集示例(感谢@aosmith):

dat = data.frame(email = c(rep(c("user1@hotmail.com", "user2@gmail.com"), each = 2), NA),
              name = c(NA, "Alfred C.", NA, "Bob V.", "Cathy L."),
              var1 = c(2, 2, NA, NA, 1),
              var2 = c(1, NA, 3, NA, 1),
              var3 = c(NA, NA, 1, 0, 2),
              var4 = c(0, NA, NA, NA, NA))

我想合并我的观察结果,最后一行等于一个人。要识别我使用该电子邮件的人。当没有电子邮件时,我想保留所有观察结果(如果电子邮件遗失,我不希望R删除观察结果。每次观察都认为没有电子邮件被认为是一种独特的观察结果。)

对于我们可以发现相同电子邮件地址的时代,我们需要R来更新每个变量的字段,当数据丢失时,我们会在随后的观察结果(使用相同的电子邮件地址)中获得数据。如果已经有一个或多个变量的现有数据,我们希望R创建,每次都有一个新变量来存储不同的值。

这是一个让人们更容易理解的例子。

我们需要改变这样的事情:

          email        name    var1 var2 var3 var4 ... var200
user1@hotmail.com      <NA>     2    1   NA    0   ...   .
user1@hotmail.com    Alfred C.  2   NA   NA   NA   ...   .
  user2@gmail.com      <NA>    NA    3    1   NA   ...   .
  user2@gmail.com     Bob V.   NA   NA    0   NA   ...   .
             <NA>    Cathy L.   1    1    2   NA   ...   .

进入这样的事情(将行与相同的电子邮件相结合,并将同一个人的所有信息保存在一行中,但也可以在我们无法识别该人与电子邮件地址相同时保留信息。所以,如果电子邮件是NA我们必须保持它好像是一个独特的人):

           email           name      var1    var2    var3a   var3b   var4   ...  var200

  user1@hotmail.com      Alfred C.     2       1      NA       NA     0      .      . 
    user2@gmail.com       Bob V.      NA       3      1        0      NA     .      . 
               <NA>      Cathy L.      1       1      2        .      NA     .      . 
    userX@email.com         .          .      etc    etc      etc    etc    etc    etc 

有一种简单的方法吗?我和dplyr和tidyr挣扎了两天...... 最后,一行应包含我们能够使用电子邮件变量识别的一个人的信息。我们还需要保留我们无法识别属于一个人的所有其他观察结果。

感谢您的帮助和时间!

1 个答案:

答案 0 :(得分:3)

我想出了一个选项,以防你不知道主题中每个变量有多少值。您将看到大多数步骤(为单独的列创建单独的名称)。

过程是使用gather将数据集放入长格式,删除每个主题和变量组合的缺失值和重复值,为每个变量有多个值时创建变量名称(添加b,c等等到变量名称的末尾),然后用spread将数据集放回宽格式。

dat = data.frame(email = rep(c("user1@hotmail.com", "user2@gmail.com"), each = 2),
                  twitter = c(NA, "user1", NA, "user2"),
                  var1 = c(2, 2, NA, NA),
                  var2 = c(1, NA, 3, NA),
                  var3 = c(NA, NA, 1, 0),
                  var4 = c(0, NA, NA, NA))
library(dplyr)
library(tidyr)

dat %>%
    gather(allvar, value, twitter:var4) %>%
    group_by(email, allvar) %>%
    filter(!is.na(value) & !duplicated(value)) %>%
    mutate(allvar2 = paste0(allvar, c("", letters[2:26])[1:n()])) %>% 
    ungroup() %>%
    select(-allvar) %>%
    spread(allvar2, value, convert = TRUE)

Source: local data frame [2 x 7]

              email twitter var1 var2 var3 var3b var4
1 user1@hotmail.com   user1    2    1   NA    NA    0
2   user2@gmail.com   user2   NA    3    1     0   NA

编辑以查找缺少某些电子邮件地址时的新示例

我不完全清楚你是否总是有Twitter或电子邮件信息或两者兼而有之 - 如果是这样的话,我认为可以通过在@ jazurro&#39中使用na.locf来填充Twitter来简化这一过程。 ;回答并使用电子邮件和推特的组合作为分组变量。

要保留没有电子邮件的行,您可以将其过滤掉,执行所需的一切,然后rbind_list将它们重新输入。在这种情况下,命名重复的变量,例如var3和{{1将会为您解决(可以将它们命名为var3bvar3a,但不会为此rbinding方法工作。)

var3b