Reputation: 191
Having a matrix like:
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 11 14 17 20 23 26
[2,] 12 15 18 21 24 27
[3,] 13 16 19 22 25 28
I want to get only the rows that have sum of digits for each row between 2 values.
Sum of digits for each row:
[1] 30
[2] 38
[3] 42
so if I want to get only rows where sum of digits is between 31
and 40
, then
only the row 2
with value 38
must be returned.
Upvotes: 4
Views: 162
Reputation: 12935
You could do:
l <- strsplit(as.character(t(m)), "")
mx <- max(lengths(l))
res <- rowSums(matrix(as.numeric(unlist(lapply(l, 'length<-', mx))),
ncol = ncol(m)*mx, byrow = TRUE), na.rm = TRUE)
m[res>31 & res<42,]
#[1] 12 15 18 21 24 27
l
is the list of all digits in m
mx
is the maximum length of a number in m
just in case the number of digits are not equal for all numbers within m
(for your case it is 2
)
Then you make all list elements of equal length (by adding NA
) and getting a matrix out of list elements where rowSums
gives you the sum of digits per row in m
res
), you filter out those rows of interest.Upvotes: 0
Reputation: 887501
We can do
i1 <- apply(m1, 1, function(x) {
v1 <- sum(unlist(lapply(strsplit(as.character(x), ""), as.numeric)))
v1 > 31 & v1 < 40})
m1[i1, , drop = FALSE]
# [,1] [,2] [,3] [,4] [,5] [,6]
#[1,] 12 15 18 21 24 27
Or
i1 <- sapply(strsplit(do.call(paste0, as.data.frame(m1)), ""),
function(x) sum(as.integer(x)))
m1[i1, , drop = FALSE]
Or we can do
f1 <- Vectorize(function(x) sum(floor(x / 10^(0:(nchar(x) - 1))) %% 10))
i1 <- rowSums(t(apply(m1, 1, f1))) %in% 31:40
m1[i1, , drop = FALSE]
m1 <- matrix(11:28, nrow = 3)
Upvotes: 3