Dihan
Dihan

Reputation: 311

find a subset using lapply/apply in a data frame

I have two data frames cell and support (shown below). I want a subset of 'cell' using the following condition: all the rows of 'support' that match with vector b element-wise. my output will consist of all those rows of 'cell'.

a<-c(0,1,0)
b<-c(0,0,1)
level = c(3,2,4)
zero = c(1,2,1)


cell <- do.call(expand.grid, lapply(level, seq))    #create all cell
support <- t(apply(cell, 1, function(x) +(x != zero)))


> cell
   Var1 Var2 Var3
1     1    1    1
2     2    1    1
3     3    1    1
4     1    2    1
5     2    2    1
6     3    2    1
7     1    1    2
8     2    1    2
9     3    1    2
10    1    2    2
11    2    2    2
12    3    2    2
13    1    1    3
14    2    1    3
15    3    1    3
16    1    2    3
17    2    2    3
18    3    2    3
19    1    1    4
20    2    1    4
21    3    1    4
22    1    2    4
23    2    2    4
24    3    2    4
> support
      Var1 Var2 Var3
 [1,]    0    1    0
 [2,]    1    1    0
 [3,]    1    1    0
 [4,]    0    0    0
 [5,]    1    0    0
 [6,]    1    0    0
 [7,]    0    1    1
 [8,]    1    1    1
 [9,]    1    1    1
[10,]    0    0    1
[11,]    1    0    1
[12,]    1    0    1
[13,]    0    1    1
[14,]    1    1    1
[15,]    1    1    1
[16,]    0    0    1
[17,]    1    0    1
[18,]    1    0    1
[19,]    0    1    1
[20,]    1    1    1
[21,]    1    1    1
[22,]    0    0    1
[23,]    1    0    1
[24,]    1    0    1
> hD<-lapply(1:nrow(cell), function (x) cell[which(sum(support[x,]==b)==3),])
> do.call(rbind, hD)
  Var1 Var2 Var3
1    1    1    1
2    1    1    1
3    1    1    1

I tried to use lapply but I am not getting the expected output. My output should be row 10,16, and 22 of the cell (shown below) as rows 10,16, and 22 of support match exactly with vector b. I do not want to use any loop.

  Var1 Var2 Var3
1    1    2    2
2    1    2    3
3    1    2    4

Upvotes: 1

Views: 84

Answers (4)

akrun
akrun

Reputation: 887118

We can also do

cell[!rowSums(support != b[col(support)]),]
#   Var1 Var2 Var3
#10    1    2    2
#16    1    2    3
#22    1    2    4

Upvotes: 0

Ronak Shah
Ronak Shah

Reputation: 388982

You could compare b values to each row in support by transposing it and select the rows in cell where all values match.

cell[colSums(t(support) == b) == length(b), ]

#   Var1 Var2 Var3
#10    1    2    2
#16    1    2    3
#22    1    2    4

This can also be done using sweep :

cell[rowSums(sweep(support, 2, b, `==`)) == length(b), ]

To compare with both a and b we can match them individually :

cell[colSums(t(support) == b) == length(b) | 
     colSums(t(support) == a) == length(a), ]

Or use lapply :

cell[Reduce(`|`, lapply(list(a, b), function(x) 
           colSums(t(support) == x) == length(x))), ]

Upvotes: 0

jay.sf
jay.sf

Reputation: 72828

Here an apply logic, which is applicable to both requirements.

cell[apply(support, 1, function(x) all(x == b)), ]
#    Var1 Var2 Var3
# 10    1    2    2
# 16    1    2    3
# 22    1    2    4

cell[apply(support, 1, function(x) all(x == b) | all(x == a)), ]
#    Var1 Var2 Var3
# 1     1    1    1
# 10    1    2    2
# 16    1    2    3
# 22    1    2    4

Upvotes: 0

ThomasIsCoding
ThomasIsCoding

Reputation: 101373

Here is another base R option

subset(cell,Reduce(`&`,as.data.frame(t(t(support)==b))))

or

subset(cell,Reduce(`&`,as.data.frame(support == t(replicate(nrow(support),b)))))

which gives

   Var1 Var2 Var3
10    1    2    2
16    1    2    3
22    1    2    4

Upvotes: 0

Related Questions