Простой способ добавить наблюдения в существующий фрейм данных?

У меня есть существующий фрейм данных, в который я хотел бы добавить обновленные наблюдения. Я могу идентифицировать эти обновленные наблюдения по идентификатору и переменной временной точки. Я попытался удалить устаревшие наблюдения из существующего фрейма данных, а затем попытался использовать функцию 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

Допустим, я хочу изменить переменную оценки 1 для третьего наблюдения (для которого ID == 2 и время == "час 1") с 3 на 5.

Я пробовал создать новый фрейм данных, который называется Practice1:

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

Что удаляет третье наблюдение, а затем создает еще один новый фрейм данных с исправленными наблюдениями, называемый практикой2:

   ID     Time  score 1  score 2 
    2   hour 1        3        4

Затем я попытался сделать что-то вроде этого:

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

Однако я получаю повторяющиеся столбцы, и когда я пытаюсь включить несколько переменных в оператор by = функции слияния, я получаю эту ошибку:

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

Что может быть связано с лонгитюдным характером данных?

Спасибо


person baldirony    schedule 19.04.2017    source источник
comment
Предоставьте несколько примеров данных stackoverflow.com/questions/5963269/   -  person neilfws    schedule 20.04.2017
comment
Извините, я попытался добавить несколько примеров данных в свою правку.   -  person baldirony    schedule 20.04.2017
comment
@ G5W Да, действительно; Я отредактировал сообщение соответствующим образом. Спасибо.   -  person baldirony    schedule 20.04.2017


Ответы (3)


Вы можете выполнить замену переменной во фрейме данных. Например.:

practice[["Score 1"]][practice$ID == 2 & practice$Time=="hour 1"] <- 5
person thc    schedule 20.04.2017
comment
Или practice[practice$ID == 2 & practice$Time == "hour 1", "score 1"] <- 5, чтобы немного упростить - person thelatemail; 20.04.2017
comment
Кроме того, вам нужно ссылаться на practice$Time, а не только на Time. - person thelatemail; 20.04.2017
comment
Спасибо, это может быть именно то, что мне нужно. Я думал, что двойные скобки используются только при работе со списками. - person baldirony; 20.04.2017
comment
@baldirony - data.frames - это списки. - person thelatemail; 20.04.2017
comment
@thelatemail А, значит, dfs - это просто списки object = 1? - person baldirony; 20.04.2017
comment
@baldirony - data.frames - это список, в котором каждый столбец представляет собой элемент списка одинаковой длины. Сравните as.list(mtcars) с mtcars - person thelatemail; 20.04.2017
comment
Да, data.frames является производным классом списков и наследует все методы списков: programiz.com / r-programming / наследование - person thc; 20.04.2017

Вот обновление с использованием dplyr::mutate. Примечание. Я переименовал столбцы, чтобы убрать пробелы.

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

Если у вас уже есть новые данные в 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
person alistaire    schedule 20.04.2017