Удаление незавершенных обращений в нескольких строках в R studio

#r #time #rstudio #rows #missing-data

#r #время #rstudio #строки #отсутствует -данные

Вопрос:

Допустим, у меня есть продольный набор данных, как показано ниже

 ID <- c(1, 1, 2, 2, 3, 3, 4, 4)
time <- c(1, 2, 1, 2, 1, 2, 1, 2)
value <- c(7, 5, 9, 2, NA, 3, 7, NA)

mydata <- data.frame(ID, time, value)

  ID time value
1  1    1     7
2  1    2     5
3  2    1     9
4  2    2     2
5  3    1    NA
6  3    2     3
7  4    1     7
8  4    2    NA
 

В этом наборе данных у нас есть 4 обращения с данными в два момента времени (скажем, до и после обработки)

Что-то, что я хочу сделать, это установить критерии для удаления любого обращения, которое не завершено для обоих временных точек. В этом примере я хотел бы удалить ID3 (у которого отсутствует временная точка 1) и ID4 (у которого отсутствует временная точка 2). Как показано ниже:

   ID time value
1  1    1     7
2  1    2     5
3  2    1     9
4  2    2     2
 

Мне не очень повезло. Я пробовал варианты complete.cases() или which() безрезультатно

Я все еще новичок в R и был бы очень признателен, если бы кто-нибудь мог мне помочь

Редактировать: Спасибо, Ронак, за ответ на мой вопрос. После анализа моих реальных данных я столкнулся со второй проблемой. Мои фактические данные в большей степени отражены в приведенном ниже:

 ID <- c(1, 1, 2, 2, 3, 3, 4, 4, 5, 6, 7, 8)
time <- c(1, 2, 1, 2, 1, 2, 1, 2, 1, 1, 1, 1)
value <- c(7, 5, 9, 2, NA, 3, 7, NA, 8, 9, 7, 6)

mydata <- data.frame(ID, time, value)



    ID time value
1   1    1     7
2   1    2     5
3   2    1     9
4   2    2     2
5   3    1    NA
6   3    2     3
7   4    1     7
8   4    2    NA
9   5    1     8
10  6    1     9
11  7    1     7
12  8    1     6
 

Где я также хотел бы удалить обращения 5, 6, 7 и 8. Эти идентификаторы содержат запись для времени 1, но не для времени 2. Надеюсь, это имеет смысл

Большое спасибо

Комментарии:

1. library(dplyr) ; mydata %>% group_by(ID) %>% filter(!any(is.na(c(time, value))))

Ответ №1:

Если вы переведете свои данные в широкий формат (где каждый момент времени представлен в виде отдельного столбца), тогда вы можете использовать na.omit . Использование dplyr и tidyr функции:

 library(dplyr)    
mydata <- mydata %>%
tidyr::spread(key=time, value=value) %>% # reformat to wide
na.omit() %>% # delete cases with missingness on any variable (i.e. any time point)
tidyr::gather(key="time", value="value", -ID) # put it back in long format

> mydata
  ID time value
1  1    1     7
2  2    1     9
3  1    2     5
4  2    2     2
 

Обратите внимание, что это будет работать (будут сохранены только обращения с полными данными как для времени 1, так и для времени 2), даже если у вас отсутствует момент времени без явного NA, присутствующего в данных, например:

 > mydata
   ID time value
1   1    1     7
2   1    2     5
3   2    1     9
4   2    2     2
5   3    1    NA
6   3    2     3
7   4    1     7
8   4    2    NA
9   5    1     8
10  6    1     9
11  7    1     7
12  8    1     6
 

Комментарии:

1. Большое вам спасибо, Роуз, — это отлично ответило на мой запрос. Я бы никогда не понял этого самостоятельно. Спасибо всем за их ответы

2. Рад помочь! Мне нравятся dplyr tidyr пакеты и для обычных манипуляций с фреймами данных, подобных этому.

3. Спасибо, Роуз, если вы меня порадуете, у меня есть еще один вопрос… скажем, я должен был добавить третий момент времени. Когда я пытаюсь переформатировать в wide с помощью tidyr::spread(ключ = время, значение = значение) , он выдает ошибку повторяющиеся идентификаторы для строк . Я не совсем уверен, как настроить код для трех временных точек. Был бы признателен, если у вас есть какие-либо предложения

4. Эта ошибка не связана с добавлением третьей временной точки. Что-то еще идет не так. Возможно, у вас есть какие-либо случаи, когда один и тот же идентификатор имеет одинаковое время более одного раза? Быстрый способ проверить — получить количество уникальных строк, используя только ID и time, и сравнить это с количеством строк во всем наборе данных. Они должны быть одинаковыми: nrow(unique(dplyr::select(my_data, ID, time))); nrow(my_data)

5. Еще раз спасибо, Роуз, вы совершенно правы. Ваш код продемонстрировал явное несоответствие. Я думал, что это может быть так, но ранее отфильтровал свой набор данных, означающий, что номера строк не синхронизированы. Я искал дубликат не в том месте. Действительно ценю, что вы нашли время, чтобы помочь 🙂

Ответ №2:

Вы можете сделать это легко с sqldf помощью .

 library(sqldf)    
sqldf(' select * from (select ID, count(*) as cnt from mydata where value is not null group by id having cnt >1 ) t1 inner join mydata t2 on t1.ID=t2.ID')
 

Вы должны выбрать те идентификаторы, число которых больше 1 и в значениях которых нет NA, а затем снова присоединиться к исходным данным.

Ответ №3:

@Ronak уже предоставил

mydata[!mydata$ID %in% mydata$ID[is.na(mydata$value)], ]

Для второй части вы можете просто группировать по каждому идентификатору и фильтровать по их частоте

k2 <- data.frame(table(mydata$ID))

k2$Var1[k2$Freq > 1]

а затем сделайте что-то вроде

mydata[mydata$ID %in% k2$Var1[k2$Freq > 1],]

Ответ №4:

Смотрите Обновленный ответ

 # Eliminates ID cases with NA
mydata = mydata[!mydata$ID %in% mydata[!complete.cases(mydata) ,]$ID, ]

library(plyr)
# counts all the IDs
cnt = count(mydata, "ID")
# Eliminates any ID that doesn't have 2 observations
mydata[mydata$ID %in% cnt[cnt$freq == 2, ]$ID, ]

  ID time value
1  1    1     7
2  1    2     5
3  2    1     9
4  2    2     2
 

Комментарии:

1. Спасибо за предложение @Ash

2. @perkot смотрите Обновленный ответ на ваш обновленный вопрос

3. Спасибо всем за ваши предложения — мне сейчас нужно бежать с работы, но я проверю все предложения сегодня вечером

4. Привет @Ash — у меня только что была возможность попробовать ваше решение, оно отлично сработало. Спасибо, что нашли время помочь. Более того, это решение позволяет мне изменять код для дополнительных временных точек