Подсчитать число вхождений нуля между ненулевым значением в R - PullRequest
0 голосов
/ 27 февраля 2019

У меня есть матрица

mat <- matrix(c(64,76,0,0,78,35,45,0,0,4,37,0,66,46,0,0,0,0,3,0,71,0,28,97,0,30,55,65,116,30,18,0,0,143,99,0,0,0,0,0), nrow=4, byrow=T)

mat
     [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
[1,]   64   76    0    0   78   35   45    0    0     4
[2,]   37    0   66   46    0    0    0    0    3     0
[3,]   71    0   28   97    0   30   55   65  116    30
[4,]   18    0    0  143   99    0    0    0    0     0

Я хочу создать список, который подсчитывает число вхождений нуля между ненулевым значением

[[1]]
[1] 2 2

[[2]]
[1] 1 4 1

[[3]]
[1] 1 1

[[4]]
[1] 2 5

Ответы [ 4 ]

0 голосов
/ 01 марта 2019

Если по какой-то причине у вас есть матрица с множеством строк, и вам нужно сделать это на несколько секунд быстрее (вряд ли я знаю), вы можете использовать метод ниже

library(dplyr)

rle(c(t(mat))) %>% 
  do.call(what = data.frame) %>% 
  mutate(mrow = (cumsum(lengths) - 1) %/% ncol(mat)) %>% 
  {split(.$lengths[!.$values], .$mrow[!.$values])}

# $`0`
# [1] 2 2
# 
# $`1`
# [1] 1 4 1
# 
# $`2`
# [1] 1 1
# 
# $`3`
# [1] 2 5

Бенчмарк

mat <- mat[sample(nrow(mat), 1e6, T),]

f1 <- function(mat){
  apply(mat, 1, function(x) {
   with(rle(x), lengths[values == 0])
 })
}
f2 <- function(mat){
rle(c(t(mat))) %>% 
  do.call(what = data.frame) %>% 
  mutate(mrow = (cumsum(lengths) - 1) %/% ncol(mat)) %>% 
  {split(.$lengths[!.$values], .$mrow[!.$values])}
}

microbenchmark::microbenchmark(f1(mat), f2(mat), times = 10)
# Unit: seconds
#     expr       min        lq      mean    median        uq       max neval
#  f1(mat) 28.346335 28.978307 30.633423 30.720702 31.504075 35.049800    10
#  f2(mat)  3.683452  3.916681  4.099936  4.086634  4.250613  4.482668    10
0 голосов
/ 27 февраля 2019

Вы можете использовать rle, который вычисляет количество последовательных чисел

mat <- matrix(c(64,76,0,0,78,35,45,0,0,4,37,0,66,46,0,0,0,0,3,0,71,0,28,97,0,30,55,65,116,30,18,0,0,143,99,0,0,0,0,0), nrow=4, byrow=T)
apply(mat,1,function(x) {
  value = rle(x==0)
  value$length[value$values]
  })
0 голосов
/ 27 февраля 2019

Еще один

setNames(object = lapply(X = data.frame(t(mat)),
                         FUN = function(x)
                             with(rle(x == 0), lengths[values])),
         nm = NULL)
#[[1]]
#[1] 2 2

#[[2]]
#[1] 1 4 1

#[[3]]
#[1] 1 1

#[[4]]
#[1] 2 5
0 голосов
/ 27 февраля 2019

Все, что вам нужно, это rle

> apply(mat, 1, function(x) {
   rle(x)$length[rle(x)$values == 0]
 })
[[1]]
[1] 2 2

[[2]]
[1] 1 4 1

[[3]]
[1] 1 1

[[4]]
[1] 2 5
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...