Reputation: 1235
It must be something very obvious but somehow I can't figure it out...
Let's say I have a matrix M like this:
A B name.C name.D name.E
row 1 0.05160408 0.11090351 1.0206272 -0.318932333 0.2983051
row 2 0.04906006 0.10500725 0.9654350 -0.253736273 0.2883013
row 3 0.04651603 0.09940203 0.9102428 -0.188540213 0.2782974
row 4 0.04397201 0.09413984 0.8550506 -0.123344153 0.2682935
row 5 0.04142799 0.08928137 0.7998585 -0.058148093 0.2582896
row 6 0.03888397 0.08489596 0.7446663 0.007047967 0.2482858
row 7 0.03633994 0.08106041 0.6894741 0.072244028 0.2382819
row 8 0.03379592 0.07785605 0.6342819 0.137440088 0.2282780
And I want to subset a matrix with only rows where all the values in names.* columns are positive.
I can produce a logical matrix like that: M[grep("^name",colnames(M))] > 0
. But how to get the real numbers then? As a matrix, again, not as a vector?
Upvotes: 0
Views: 3763
Reputation: 121568
Personaly I would use rowSums
for such task , but you can also use another method (for fun) based on %*%
operator :
indx <- grep('^name', colnames(mat))
xx = (mat[,indx] >0)%*%t(mat[,indx] >0)
mat[colnames(xx)[diag(xx)==length(indx)],]
# A B name.C name.D name.E
# row 6 0.03888397 0.08489596 0.7446663 0.007047967 0.2482858
# row 7 0.03633994 0.08106041 0.6894741 0.072244028 0.2382819
# row 8 0.03379592 0.07785605 0.6342819 0.137440088 0.2282780
Upvotes: 2
Reputation: 2986
Taking the data from @Akrun above a oneliner would be:
m1[-unique(which(m1[,3:5] < 0) %% nrow(m1)),]
explanation:
which(m1[,3:5] < 0)
gives you the indices of the negative numbers in the columns you are interested in
and with %% nrow(m1)
you get the row indices where you find negative numbers. You use unique
as we are only interested in the unique rows.
Upvotes: 1
Reputation: 887098
You could create a column index using grep
for the column names that start with name
. Then subset
those columns and check whether the elements are greater than (>
) 0. Then do the sum of each row of the logical index with rowSums
and check if that equals to the length
of indx
. Use that to subset the rows of m1
.
indx <- grep('^name', colnames(m1))
m1[rowSums(m1[,indx]>0)==length(indx),]
# A B name.C name.D name.E
#row 6 0.03888397 0.08489596 0.7446663 0.007047967 0.2482858
#row 7 0.03633994 0.08106041 0.6894741 0.072244028 0.2382819
#row 8 0.03379592 0.07785605 0.6342819 0.137440088 0.2282780
Another option would to convert the logical index columns (m1[,indx]>0
) to data.frame
and check whether each row have all TRUE
using &
and Reduce
m1[Reduce(`&`, as.data.frame(m1[,indx] >0)),]
Or you could use apply
with MARGIN=1
to check the condition for each row. But, this method may be a bit slower for large datasets. (from @David Arenburg's comments)
m1[apply(m1[, indx], 1, function(x) all(x > 0)), ]
m1 <- structure(c(0.05160408, 0.04906006, 0.04651603, 0.04397201, 0.04142799,
0.03888397, 0.03633994, 0.03379592, 0.11090351, 0.10500725, 0.09940203,
0.09413984, 0.08928137, 0.08489596, 0.08106041, 0.07785605, 1.0206272,
0.965435, 0.9102428, 0.8550506, 0.7998585, 0.7446663, 0.6894741,
0.6342819, -0.318932333, -0.253736273, -0.188540213, -0.123344153,
-0.058148093, 0.007047967, 0.072244028, 0.137440088, 0.2983051,
0.2883013, 0.2782974, 0.2682935, 0.2582896, 0.2482858, 0.2382819,
0.228278), .Dim = c(8L, 5L), .Dimnames = list(c("row 1", "row 2",
"row 3", "row 4", "row 5", "row 6", "row 7", "row 8"), c("A",
"B", "name.C", "name.D", "name.E")))
Upvotes: 3