2016-01-06 2 views
1

У меня есть кадр данных, который выглядит следующим образом:Вычисление функции смежных состояний с dplyr без использования group_by?

States <- data.frame(State = c('a','a','b','c','c','a','b'),Duration = c(2,3,5,4,7,2,1)) 

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

State Duration 
a  5 
b  5 
c  11 
a  2 
b  1 

Быстрый ответ использует group_by, но это неправильно;

States %>% group_by(State) %>% summarise(Total = sum(Duration)) 

дает

State Total 
    (fctr) (dbl) 
1  a  7 
2  b  6 
3  c 11 

Как бы вы сделать это?

Спасибо,

Билл

Вот более простой вариант, который может быть ближе к сути моей проблемы.

States <- data.frame(State = c('a','a','a','b','c','c','b','a','b','d'),Duration = c(0,2,2,3,0,5,4,7,2,1)) 

    States 
    State Duration 
1  a  0 
2  a  2 
3  a  2 
4  b  3 
5  c  0 
6  c  5 
7  b  4 
8  a  7 
9  b  2 
10  d  1 

Я хочу подвести итог продолжительности, проведенной в смежных посещениях штатов. В этом случае, это

Другими словами, вы берете на себя последний срок для каждого государственного визита, а первая длительность 0, если есть более чем одна запись для этого визита (я не дизайн данных , Я просто работаю с ним).

Если я использую group_by, как указано выше, dplyr запускает кадр данных по состоянию, и это дает мне неправильный ответ: одна запись для каждого состояния, а не одна запись за посещение.

Помогло ли это? Я думаю, что они оба связаны между собой: есть ли способ объединить строки, не переставляя их?

+0

@DatamineR ах - я прочитал его как второй фрагмент кода - желаемый результат, третий кусок - это то, что он пытался, а четвертый фрагмент кода - результат его неправильной попытки. – tospig

+0

Чтобы уточнить, первый кодовый блок создает входные данные. Второй показывает, что я хочу. Третий показывает неправильный код с помощью group_by, а четвертый показывает результат неправильного кода. Я ищу код, который производит второй блок кода. @tospig, вы правы. – Bill

ответ

3

Вы можете создать новую переменную группировки, используя кодирование длины прогона. Я уверен, что есть более dplyr-ish способ сделать некоторые из этих шагов.

rles <- rle(as.character(States$State)) 
States$new.groups <- rep(LETTERS[seq_along(rles[[1]])], rles$lengths) 

durations <- States %>% group_by(new.groups) %>% 
       summarise(Total = sum(Duration)) %>% 
       transform(States = new.groups, new.groups = NULL) 

durations$State <- rles$values # assign the appropriate values to duration$State 

#Source: local data frame [5 x 2] 
# 
# State Total 
# (chr) (dbl) 
#1  a  5 
#2  b  5 
#3  c 11 
#4  a  2 
#5  b  1 

Если вы ОК с включения data.table функцию, вы можете использовать очень хороший rleid для немного чище ищет код:

library(data.table) 
States$new.groups <- rleid(States$State) 

    durations <- States %>% group_by(new.groups) %>% 
       summarise(Total = sum(Duration)) %>% 
       transform(States = new.groups, new.groups = NULL) 

durations$States <- rle(as.character(States$State))$values # still had to use regular rle here 
+1

rle, очень интересная функция, которую я не знал. – PereG

+0

@PereG это потрясающая функция. На самом деле функция 'rleid'' data.table' может быть даже лучше для этой задачи! – Jota

+0

да !, спасибо за обмен и отзыв! – PereG

1

Вычислить фиктивная переменная

for (i in 1:(dim(States)[1]-1)){ 
     States$new[1] <- "A" 
     States$new[i+1] <- ifelse(States$State[i] == States$State[i+1], 
      States$new[i], 
      LETTERS[i] 
    )  
} 

построить новый data.frame и форматировать его

data <- data.frame(cbind(as.character(unique(States$State)), rowsum(States$Duration, States$new))) 
names(data) <- c("State", "Duration") 
rownames(data) <- NULL 
data 

Это не элегантный код, но с вашими данными, она работает.


Для достижения предлагаемого решения после редактирования:

States2 <- States[States$Duration != 0,] 

Теперь же для цикла

for (i in 1:(dim(States2)[1]-1)){ 
     States2$new[1] <- "A" 
     States2$new[i+1] <- ifelse(States2$State[i] == States2$State[i+1], 
           States2$new[i], 
           LETTERS[i] 
    )  
} 

И новый блок кода:

library(data.table) 
States2 <- as.data.table(States2) 
# set "new" as the key variable 
setkey(States2, new)  
# select the last row of new 
States3 <- as.data.table(States2[unique(States2$new), mult = "last"]) 
# clean the data 
States3[, new := NULL] 
States3 

enter image description here

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