Ifelse in a group in R

I have a dataset

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

I am trying to create variables xand y, group by ID and Eval. For each identifier if Eval = A, and med = "h" or "k"I install x = 1, other wise x = 0, if Eval = B and med = "h" or "k"I set y = 1the other wise y = 0. I use a way that I do not like it, I have an answer, but it seems that it is not.

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

Then I need to collapse the line to get a unique identifier, I don’t know how to collapse the lines, any idea?

Output

 ID x y
 1  0 0
 2  1 1
 3  0 1
 4  0 1
+4
source share
4 answers

"x" "y", "", NA, (as.integer)

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

'y'

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

, (:=), , "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

, , .

+6

OP...

" x y, Eval. , Eval = A med =" h "" k ", x = 1, x = 0, Eval = B med =" h "" k ", y = 1, y = 0. [...] , "

...

ID Eval , med 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 ( ).

+5

Here is my solution dplyr, as I find it more readable than 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)))
+1
source

One line solution for folding your result lines:

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
+1
source

Source: https://habr.com/ru/post/1648132/


All Articles