2015-12-16 3 views
0

У меня есть немного сложная проблема для решения.Удаление последовательных строк в группе строк для больших наборов данных в R

Предположим, у меня есть этот набор данных

Id Name Price sales Profit Month Category Mode Supplier 
1 A  0  0  0  1  X K  John 
1 A  0  0  0  2  X K  John 
1 A  0  0  0  3  X K  John 
1 A  2  5  0  4  X L  Sam 
1 A  2  3  4  5  X L  Sam 
1 A  0  0  0  6  X L  Sam 
2 C  2  4  9  1  X M  John 
2 C  0  0  0  2  X L  John 
2 C  0  0  0  3  X K  John 
2 C  2  8  0  4  Y M  John 
2 C  2  8  10  5  Y K  John 
2 C  0  0  0  6  Y K  John 
3 E  0  0  0  1  Y M  Sam 
3 E  0  0  0  2  Y L  Sam 
3 E  2  5  9  3  Y M  Sam 
3 E  0  0  0  4  Z M  Kyle 
3 E  0  0  0  5  Z L  Kyle 
3 E  0  0  0  6  Z M  Kyle 

Теперь я хочу, чтобы удалить эти строки из кадра данных, за исключением тех продуктов Id, которые имеют нулевое значение Price, sales и profit в течение трех месяцев подряд. Как удалить строки только в определенной группе в этом случае Id

Ожидаемых выходного

Id Name Price sales Profit Month Category Mode Supplier 
1 A  2  5  0  4  X L  Sam 
1 A  2  3  4  5  X L  Sam 
1 A  0  0  0  6  X L  Sam 
2 C  2  4  9  1  X M  John 
2 C  0  0  0  2  X L  John 
2 C  0  0  0  3  X K  John 
2 C  2  8  0  4  Y M  John 
2 C  2  8  10  5  Y K  John 
2 C  0  0  0  6  Y K  John 
3 E  0  0  0  1  Y M  Sam 
3 E  0  0  0  2  Y L  Sam 
3 E  2  5  9  3  Y M  Sam 

Это просто воспроизводит образец, мои оригинальные данные имеют более 800K строк. Поэтому я ищу некоторые функции, которые могут быть достигнуты и на большом наборе данных.

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

library(data.table) 
as.data.table(mydf)[, N := .N, by = .(Id, rleid(Price == 0 & sales == 0 & Profit == 0))][ 
    !(Price==0 & sales == 0 & Profit == 0 & N >= 2)] 

Это один, когда я попытался получена ошибка, что 'could not find rleid function' и я имел data.table пакет установки и загружен

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

+0

Для того, чтобы удалить строки с идентификатором продукта, который имеет нули три месяца подряд сделать строки должны иметь только идентификатор одинаковые или также другие столбцы, такие как категория, режим или поставщик? – Sam

+0

Возможно, вам нужно обновить установленный пакет 'data.table'. –

+0

У вас есть 'packageVersion (" data.table ")> =" 1.9.6 "'? Посмотрите на [история версий] (https://github.com/Rdatatable/data.table). – lukeA

ответ

0

Это скорее «самодельный», но, возможно, поможет (мой пример немного проще, но идея та же):

library("dplyr") 

# just an example: 

month <- rep(1:7, 3) 
id <- rep(c("A", "C", "E"), each=7) 
price <- c(0,0,0,2,2,0,2,0,0,2,2,0,0,0,2,0,0,0, 1, 1, 1) 
sales <- c(0,0,0,4,3,0,2,0,0,1,3,0,0,0,3,0,0,0, 1, 1, 1) 
supplier <- rep(c("john", "anna", "ben"), 7) 

data.frame(id, price, sales, month, supplier) -> dane 

# lag from a vector shows everything but first element and first element become NA: 

lag1_sales <- lag(dane$sales) 
lag2_sales <- lag(dane$sales, 2) # the same, but without two first elements 

lag1_price <- lag(dane$price) 
lag2_price <- lag(dane$price, 2) 

# I add it to data_frame as columns: 

dane <- cbind(dane, lag1_sales, lag2_sales, lag1_price, lag2_price) 

# mutate creates new column with 1 if sales and price and it's two lags are equal 1, so that I have a marker when was three zeros: 

dane %>% 
    mutate(marker=ifelse(sales==0 & price==0 & 
          lag1_sales==0 & lag2_sales==0 & 
          lag1_price==0 & lag2_price==0, 1, 0)) -> dane 

# marker2 and marker3 are made to marker two rows above this triple markered above: 

marker2 <- c(dane$marker[-1], NA) 
marker3 <- c(dane$marker[-c(1, 2)], NA, NA) 

dane <- cbind(dane, marker2, marker3) 

# I take only rows, which are marked: 

dane %>% 
    filter(!(marker==1 | marker2==1 | marker3==1)) -> new_data 
0

Вот мой ответ. Этот код удаляет строки, даже если три месяца подряд, как это, например months: 2,5,6

#Generate data 
month <- rep(1:7, 3) 
id <- rep(c("1", "2", "3"), each=7) 
price <- c(0,0,0,2,2,0,2,0,0,2,2,0,0,0,2,0,0,0, 1, 1, 1) 
sales <- c(0,0,0,4,3,0,2,0,0,1,3,0,0,0,3,0,0,0, 1, 1, 1) 
test <- data.frame(id, price, sales, month) 

#Calculate how many consecutive times a combination of id, 
#price & sales is encountered 
sequence <- rle(paste(test$id,test$price,test$sales,sep="")) 

#calculate the row indexes to keep 
index <- with(sequence, lengths != 3) 
index2 <- unlist(sapply(c(1:length(index)),FUN=function(x){ 
    seq(from=index[x],to=index[x],length.out=sequence$lengths[x]) 
})) 

#store results: 
test2 <- test[index2,] 
Смежные вопросы