2015-06-03 2 views
3

У меня есть data.frame ежемесячных значений переменной для многих местоположений (столько строк), и я хочу подсчитать количество последовательных месяцев (т.е. последовательные ячейки), которые имеют значение 0. Это было бы легко, если бы его просто читали слева направо, но добавленное осложнение заключается в том, что конец года последователен к началу года.Количество последовательных вхождений определенного значения в каждую строку кадра данных в R

Например, в сокращенном примерном наборе данных ниже (с сезонами, а не месяцами), местоположение 1 имеет 3 '0' месяцев, в местоположении 2 есть 2, а 3 - нет.

df<-cbind(location= c(1,2,3), 
Winter=c(0,0,3), 
Spring=c(0,2,4), 
Summer=c(0,2,7), 
Autumn=c(3,0,4)) 

Как я могу подсчитать эти последовательные нулевые значения? Я посмотрел rle, но я до сих пор не мудрее!

Большое спасибо за любую помощь :)

+0

как я понимаю, вы хотите считать это для каждого места? –

+0

Возможно ли, что у вас будут нули в вашем наборе данных, которые не являются последовательными? Поскольку этот случай не приведен в примере. –

+0

Да, возможно, я должен был включить это в мой пример, извините! – kim1801

ответ

2

Вы определили два случая, что длинная трасса может принять: (1) где Int он средний или (2) раскол между концом и началом каждой строки. Следовательно, вы хотите, чтобы вычислить каждое условие и взять максимум примерно так:

df<-cbind(
Winter=c(0,0,3), 
Spring=c(0,2,4), 
Summer=c(0,2,7), 
Autumn=c(3,0,4)) 

#>  Winter Spring Summer Autumn 
#> [1,]  0  0  0  3 
#> [2,]  0  2  2  0 
#> [3,]  3  4  7  4 


# calculate the number of consecutive zeros at the start and end 
startZeros <- apply(df,1,function(x)which.min(x==0)-1) 
#> [1] 3 1 0 
endZeros <- apply(df,1,function(x)which.min(rev(x==0))-1) 
#> [1] 0 1 0 

# calculate the longest run of zeros 
longestRun <- apply(df,1,function(x){ 
       y = rle(x); 
       max(y$lengths[y$values==0],0)})) 
#> [1] 3 1 0 

# take the max of the two values 
pmax(longestRun,startZeros +endZeros ) 
#> [1] 3 2 0 

Конечно еще проще решение:

longestRun <- apply(cbind(df,df),# tricky way to wrap the zeros from the start to the end 
         1,# the margin over which to apply the summary function 
         function(x){# the summary function 
          y = rle(x); 
          max(y$lengths[y$values==0], 
           0)#include zero incase there are no zeros in y$values 
         }) 

Обратите внимание, что вышеупомянутое решение работает, потому что мой df не включает location поле (столбец).

+0

Brilliiant! Единственное, что я могу винить в том, что, когда были только нули, он дважды перебирал эту строку, чтобы дать счет 24 (вместо 12, я использовал количество месяцев вместо сезонов!) Но это было легко отсортировать. Огромное спасибо! – kim1801

2

Попробуйте это:

df <- data.frame(location = c(1, 2, 3), 
       Winter = c(0, 0, 3), 
       Spring = c(0, 2, 4), 
       Summer = c(0, 2, 7), 
       Autumn = c(3, 0, 4)) 

maxcumzero <- function(x) { 
    l <- x == 0 
    max(cumsum(l) - cummax(cumsum(l) * !l)) 
} 

df$N.Consec <- apply(cbind(df[, -1], df[, -1]), 1, maxcumzero) 

df 
# location Winter Spring Summer Autumn N.Consec 
# 1  1  0  0  0  3  3 
# 2  2  0  2  2  0  2 
# 3  3  3  4  7  4  0 

Это добавляет столбец в кадр данных с указанием максимального количества раз нулевой произошло последовательно в каждой строке кадра данных. Кадр данных представляет собой столбец, привязанный к себе, чтобы иметь возможность обнаруживать последовательные нули между осенью и зимой.

Метод, использованный здесь, основан на методе Мартина Моргана в его answer to this similar question.

+0

Не уверен, что это дает правильные результаты, хотя –

+0

@DavidArenburg: Можете ли вы привести пример того, когда этого не произойдет? Он работал, как ожидалось, во всех тестах, которые я сделал. –

+0

Это не означает, что конец и начало года. См. Результат в другом ответе. Это должно быть '3 2 0' вместо' 3 1 0' –

Смежные вопросы