2016-07-17 2 views
4

Я набор данныхIfElse функциональная группа в группе в R

ID <- c(1,1,2,2,2,2,3,3,3,3,3,4,4,4) 
Eval <- c("A","A","B","B","A","A","A","A","B","B","A","A","A","B") 
med <- c("c","d","k","k","h","h","c","d","h","h","h","c","h","k") 
df <- data.frame(ID,Eval,med) 
> df 
    ID Eval med 
1 1 A c 
2 1 A d 
3 2 B k 
4 2 B k 
5 2 A h 
6 2 A h 
7 3 A c 
8 3 A d 
9 3 B h 
10 3 B h 
11 3 A h 
12 4 A c 
13 4 A h 
14 4 B k 

Я пытаюсь создать переменную x и y, группа по ID и Eval. Для каждого ID, if Eval = A, and med = "h" or "k", я установил x = 1, другой мудрый x = 0, if Eval = B and med = "h" or "k", я установил y = 1, другой мудрый y = 0. Я использую, как я не люблю его, я получил ответ, но это похоже не то, что большой

df <- data.table(df) 
setDT(df)[, count := uniqueN(med) , by = .(ID,Eval)] 
setDT(df)[Eval == "A", x:= ifelse(count == 1 & med %in% c("k","h"),1,0), by=ID] 
setDT(df)[Eval == "B", y:= ifelse(count == 1 & med %in% c("k","h"),1,0), by=ID] 


    ID Eval med count x y 
1: 1 A c  2 0 NA 
2: 1 A d  2 0 NA 
3: 2 B k  1 NA 1 
4: 2 B k  1 NA 1 
5: 2 A h  1 1 NA 
6: 2 A h  1 1 NA 
7: 3 A c  3 0 NA 
8: 3 A d  3 0 NA 
9: 3 B h  1 NA 1 
10: 3 B h  1 NA 1 
11: 3 A h  3 0 NA 
12: 4 A c  2 0 NA 
13: 4 A h  2 0 NA 
14: 4 B k  1 NA 1 

Тогда мне нужно свернуть строку, чтобы получить уникальный идентификатор, я не знаю, как свернуть строки, Есть идеи?

Выход

ID x y 
1 0 0 
2 1 1 
3 0 1 
4 0 1 
+0

Не следует ли «у» для ID 1 равен 0, поскольку есть только NAs в этом – akrun

+0

Да, вы правы – BIN

+0

Для строка 11 ваших данных, не должна 'x' быть' 1', так как Eval является 'A', а med -' h'? – Maiasaura

ответ

6

Мы создаем 'х' и 'у' переменные, сгруппированные по 'ID' без элементов NA непосредственно принуждении логического вектора в двоичный (as.integer)

df[, x := as.integer(Eval == "A" & count ==1 & med %in% c("h", "k")) , by = ID] 

и аналогично для 'у'

df[, y := as.integer(Eval == "B" & count ==1 & med %in% c("h", "k")) , by = ID] 

и обобщать его, используя any после группировки по «ID»

df[, lapply(.SD, function(x) as.integer(any(x))) , ID, .SDcols = x:y] 
# ID x y 
#1: 1 0 0 
#2: 2 1 1 
#3: 3 0 1 
#4: 4 0 1 

Если нужен компактный подход, вместо assinging (:=), мы суммируем вывод, сгруппированные по «ID», «Eval» на основании условий, а затем мы сгруппированы по 'ID', мы проверяем, есть ли any ИСТИННЫЕ значения в 'x' и 'y' путем циклизации по столбцам, описанным в .SDcols.

setDT(df)[, if(any(uniqueN(med)==1 & med %in% c("h", "k"))) { 
     .(x= Eval=="A", y= Eval == "B") } else .(x=FALSE, y=FALSE), 
    by = .(ID, Eval)][, lapply(.SD, any) , by = ID, .SDcols = x:y] 
# ID  x  y 
#1: 1 FALSE FALSE 
#2: 2 TRUE TRUE 
#3: 3 FALSE TRUE 
#4: 4 FALSE TRUE 

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

+0

, так или иначе мы не используем setDT (df) [, count: = uniqueN (med), by =. (ID, Eval)], то как свернуть строки? – BIN

+0

@Stat Обновлен с компактным подходом. Логический вектор можно легко преобразовать в двоичный. – akrun

+0

Я получил его, узнал еще один способ использования data.table – BIN

1

Это мое решение dplyr, так как оно находит его более читаемым, чем data.table.

library(dplyr) 
df %>% 
    group_by(ID, Eval) %>% 
    mutate(
    count = length(unique(med)), 
    x = ifelse(Eval == "A" & 
       count == 1 & med %in% c("h", "k"), 1, 0), 
    y = ifelse(Eval == "B" & 
       count == 1 & med %in% c("h", "k"), 1, 0) 
) %>% 
    group_by(ID) %>% 
    summarise(x1 = max(unique(x)), 
      y1 = max(unique(y))) 
5

цели Ор в ...

«Я пытаюсь создать переменную х и у, группы по идентификатору и Eval. Для каждого идентификатора, если Eval = A, и мед =„ч“ или «k», я устанавливаю x = 1, другой мудрый x = 0, если Eval = B и med = "h" или "k", я устанавливаю y = 1, другой мудрый y = 0. [...] Тогда Мне нужно, чтобы свернуть строку, чтобы получить уникальный идентификатор»

может быть упрощена ...

Для каждого идентификатора и Eval, если все значения меди равны h или все значения med равны k.

setDT(df) # only do this once 
df[, all(med=="k") | all(med=="h"), by=.(ID,Eval)][, dcast(.SD, ID ~ Eval, fun=any)] 

    ID  A  B 
1: 1 FALSE FALSE 
2: 2 TRUE TRUE 
3: 3 FALSE TRUE 
4: 4 FALSE TRUE 

Чтобы увидеть, что dcast делает, читайте ?dcast и попробуйте запустить только первую часть на своих собственных, df[, all(med=="k") | all(med=="h"), by=.(ID,Eval)].

Изменение в использовании x и y вместо A и B является простым, но нелогичным (поскольку ненужное переименование может вводить в заблуждение и приводить к дополнительной работе при появлении новых значений Eval); и это изменение вместо 1/0 вместо TRUE/FALSE (так как значения, полученные на самом деле, являются логическими).

+1

Теперь я узнаю больше обо всех() any() и dcast в data.table – BIN

+0

Это хороший. – akrun

1

Один лайнер решение для разрушения строки вашего результата:

df[,lapply(.SD,function(i) {ifelse(1 %in% i,ifelse(!0 %in% i,1,0),0)}),.SDcols=x:y,by=ID] 

    ID x y 
1: 1 0 0 
2: 2 1 1 
3: 3 0 1 
4: 4 0 1 
Смежные вопросы