Выберите строки со всеми продольными измерениями - PullRequest
0 голосов
/ 19 февраля 2019

У меня есть продольный набор данных с идентификатором, Wave (Wave1-4) и Score.Вот пример данных с той же структурой.Длина исходных данных составляет около 2000, всего 500 участников, представленных в полной форме.

   ID   Wave Score
 1 1001 1    28
 2 1001 2    27 
 3 1001 3    28
 4 1001 4    26
 5 1002 1    30
 6 1002 3    30
 7 1003 1    30
 8 1003 2    30
 9 1003 3    29
 10 1003 4   28
 11 1004 1   22
 12 1005 1   20
 13 1005 2   18
 14 1006 1   22
 15 1006 2   23
 16 1006 3   25
 17 1006 4   19

Я бы хотел выбрать «ID» со всеми четырьмя измерениями «Score».Другими словами, я хочу выбрать ряды участников с «Счетом», доступным для всех 4 волн.Я пытался выбрать строки с «идентификаторами, которые имеют данные во всех» волнах.До сих пор моя попытка была основана на этой идее: если у участника есть все четыре измерения, идентификатор будет появляться в данных четыре раза.Вот почему я попытался подсчитать количество идентификаторов,

table(data$id) == 4

, и, хотя оно показало мне номер каждого идентификатора, присутствующего в данных, я не могу выбрать соответствующие строки.

all.data <- subset(data, subset=table(data$id) == 4)

Поскольку длина исходных данных различна, они находятся в длинной форме.«Длина логического индекса должна быть 1 или 2637, а не 828». Мне понадобятся подробные данные для дальнейшего анализа, поэтому я не хочу их менять.

Ответы [ 5 ]

0 голосов
/ 22 февраля 2019

Для полноты картины предлагаем два data.table решения.Оба идентифицируют те ID s, для которых Wave имеет значения от 1 до 4. Один подход использует поднаборы, другой - присоединение.

Поднаборы

library(data.table)
setDT(df)[ID %in% dt[ , which(uniqueN(Wave) == 4L), by = ID]$ID]
      ID Wave Score
 1: 1001    1    28
 2: 1001    2    27
 3: 1001    3    28
 4: 1001    4    26
 5: 1003    1    30
 6: 1003    2    30
 7: 1003    3    29
 8: 1003    4    28
 9: 1006    1    22
10: 1006    2    23
11: 1006    3    25
12: 1006    4    19

Присоединение

library(data.table)
setDT(df)[df[, .N, .(ID, Wave)][, .N, ID][N == 4L, .(ID)], on = "ID"]

, которое возвращает тот же результат.

Данные

library(data.table)
fread("
rn ID   Wave Score
 1 1001 1    28
 2 1001 2    27 
 3 1001 3    28
 4 1001 4    26
 5 1002 1    30
 6 1002 3    30
 7 1003 1    30
 8 1003 2    30
 9 1003 3    29
 10 1003 4   28
 11 1004 1   22
 12 1005 1   20
 13 1005 2   18
 14 1006 1   22
 15 1006 2   23
 16 1006 3   25
 17 1006 4   19", drop = 1L)
0 голосов
/ 19 февраля 2019

Это быстрый data.table ответ.

  library(data.table)
  dt <- structure(list(ID = c(1001, 1001, 1001, 1001, 1002, 1002, 1003, 
  1003, 1003, 1003, 1004, 1005, 1005, 1006, 1006, 1006, 1006), 
Wave = c(1, 2, 3, 4, 1, 3, 1, 2, 3, 4, 1, 1, 2, 1, 2, 3, 
4), Score = c(28, 27, 28, 26, 30, 30, 30, 30, 29, 28, 22, 
20, 18, 22, 23, 25, 19)), row.names = c(NA, -17L), class = c("data.table", 
"data.frame"))

dt[ , .(Score, N = uniqueN(.SD)) , by = list(ID), .SDcols = c("Wave")][N == 4,]

 >   ID Score N
 1: 1001    28 4
 2: 1001    27 4
 3: 1001    28 4
 4: 1001    26 4
 5: 1003    30 4
 6: 1003    30 4
 7: 1003    29 4
 8: 1003    28 4
 9: 1006    22 4
10: 1006    23 4
11: 1006    25 4
12: 1006    19 4
0 голосов
/ 19 февраля 2019

Вы можете попробовать:

df[as.logical(with(df, ave(Wave, ID, FUN = function(x) length(x) == 4))), ]

     ID Wave Score
1  1001    1    28
2  1001    2    27
3  1001    3    28
4  1001    4    26
7  1003    1    30
8  1003    2    30
9  1003    3    29
10 1003    4    28
14 1006    1    22
15 1006    2    23
16 1006    3    25
17 1006    4    19

Или, если вы хотите сохранить основную идею, небольшое изменение кода @ jay.sf:

df[df$ID %in% names(which(table(df$ID) == 4)), ]
0 голосов
/ 19 февраля 2019

Мне нравится твой table() подход.

> table(d$ID) == 4

 1001  1002  1003  1004  1005  1006 
 TRUE FALSE  TRUE FALSE FALSE  TRUE 

Интересные идентификаторы есть в names().Таким образом, чтобы ваш код заработал, вы можете извлечь идентификаторы примерно так:

subs <- names(which(table(d$ID) == 4))

и получить желаемое подмножество, используя %in%.

all.data <- subset(d, subset=d$ID %in% subs)

Результат

> all.data
     ID Wave Score
1  1001    1    28
2  1001    2    27
3  1001    3    28
4  1001    4    26
7  1003    1    30
8  1003    2    30
9  1003    3    29
10 1003    4    28
14 1006    1    22
15 1006    2    23
16 1006    3    25
17 1006    4    19

( КСТАТИ: Всегда проверяйте с ?<name>, что вы не определяете существующие имена функций в качестве имен объектов, это сэкономит вам многоВ вашем случае введите ?data в новом сеансе перед загрузкой объекта.)

Данные

> dput(d)
structure(list(ID = c(1001L, 1001L, 1001L, 1001L, 1002L, 1002L, 
1003L, 1003L, 1003L, 1003L, 1004L, 1005L, 1005L, 1006L, 1006L, 
1006L, 1006L), Wave = c(1L, 2L, 3L, 4L, 1L, 3L, 1L, 2L, 3L, 4L, 
1L, 1L, 2L, 1L, 2L, 3L, 4L), Score = c(28L, 27L, 28L, 26L, 30L, 
30L, 30L, 30L, 29L, 28L, 22L, 20L, 18L, 22L, 23L, 25L, 19L)), class = "data.frame", row.names = c("1", 
"2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", 
"14", "15", "16", "17"))
0 голосов
/ 19 февраля 2019

вместо подачи table(data$ID), попробуйте с

ID %in% names(table(data$ID)[table(data$ID)==4])

Поскольку table дает вам количество вхождений для каждого ID (именованный вектор)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...