将观察结果添加到现有数据框的简便方法?

时间:2017-04-19 23:26:41

标签: r dplyr tidyr

我有一个现有的数据框,我想添加更新的观察结果。我可以通过ID和时间点变量识别这些更新的观察结果。我尝试从现有的数据框中删除过时的观察结果,然后尝试使用merge()函数与仅更新的观察结果的数据框合并,但我得到了重复的列。有没有一种优雅的方法(特别是使用dplyr?)

以下是我想做的一个例子: 假设我有一个df,叫做练习

practice

ID     Time  score 1 score 2 
 1   hour 1        3       7
 1   hour 2        4       2
 2   hour 1        3       4

假设我想将第3次观察的得分1变量(其中ID == 2和时间==“1小时”)从3变为5.

我尝试过制作一个名为practice1的新数据框:

ID     Time  score 1  score 2 
 1   hour 1        3        7
 1   hour 2        4        2

删除第三个观察结果,然后创建另一个带有更正观察结果的新数据框,名为practice2:

   ID     Time  score 1  score 2 
    2   hour 1        3        4

然后我尝试做这样的事情:

Practice3 <- merge(practice2, practice1, by = "ID", all = T)

但是,我会得到重复的列,当我尝试在merge函数的by =语句中包含多个变量时,我收到此错误:

Error in fix.by(by.x, x) : 'by' must specify a uniquely valid column

这可能是由于数据的纵向性质?

由于

3 个答案:

答案 0 :(得分:1)

您可以对数据框中的变量进行替换替换。 E.g:

practice[["Score 1"]][practice$ID == 2 & practice$Time=="hour 1"] <- 5

答案 1 :(得分:0)

这是使用dplyr::mutate的更新。注意:我重命名了列以删除空格。

library(dplyr)
practice %>% 
  mutate(score1 = ifelse(ID == 2 & Time == "hour 1", 5, score1))

答案 2 :(得分:0)

如果您已在data.frame中拥有新数据,则可以使用anti_join取出旧案例,然后使用bind_rows添加新案例:

library(dplyr)

practice <- read.table(text = 'ID     Time  score1 score2 
                                1    hour1       3      7
                                1    hour2       4      2
                                2    hour1       3      4', 
                       header = TRUE, stringsAsFactors = FALSE)

practice2 <- read.table(text = 'ID     Time  score1  score2 
                                 2    hour1       5       5', 
                        header = TRUE, stringsAsFactors = FALSE)

practice %>% 
    anti_join(practice2, by = c('ID', 'Time')) %>% 
    bind_rows(practice2)

#>   ID  Time score1 score2
#> 1  1 hour2      4      2
#> 2  1 hour1      3      7
#> 3  2 hour1      5      5

但是,如果practice2缺少列,则效果不佳,在这种情况下,您可以使用coalesce用新值覆盖旧值:

left_join(practice, practice2, by = c('ID', 'Time')) %>% 
    mutate(score1 = coalesce(score1.y, score1.x), 
           score2 = coalesce(score2.y, score2.x)) %>% 
    select(-contains('.'))

#>   ID  Time score1 score2
#> 1  1 hour1      3      7
#> 2  1 hour2      4      2
#> 3  2 hour1      5      5