2016-07-02 28 views
1

我有一個包含5個變量(列)的數據庫。我想要子集數據框,以檢查是否存在某個特定列的某個值。如果是這種情況,則分配1,否則爲0.然後將結果(1或0)粘貼到受限數據框的特定列,然後繼續。如何將lapply或for循環的結果添加到特定行

數據幀如下所示:

## Year Month Product Supermarket Price 
## 2015 1  67   1   10 
## 2015 1  65   1   11 
## 2015 1  69   1   15 
## 2015 2  65   2   20 
## 2015 2  67   2   25 
## 2015 2  67   3   15 
## 2015 2  69   3   12 

現在我想限制每個年份,月份和超市,並檢查產品= 65是存在的。如果是,則爲在新變量(列)中限制的行分配1。如果沒有,用lapply分配0

我曾嘗試:

prueba <- function(x) 
ifelse(any(base$Product == 65), 1, 0) 
lapply(unique(base$Supermarket) & unique(base$Year) & unique(base$Month), 
        base$NewVar <- prueba) 

,但有以下結果

Error in rep(value, length.out = nrows) : 
attempt to replicate an object of type 'closure' 

接下來,我嘗試做一個for循環:

for(i in unique(base$Supermarket)) { 
for(j in unique(base$Year)) 
for(h in unique(base$Month)) { 
try <- ifelse(any((filter(base, Supermarket == i, Year == j, Month == h))$Product == 65), 1, 0) 

base[base$Supermarket == i && base$Year ==j && base$Month == h,]$NewVar <- try 
} 
} 
} 

並有如下結果:

Error in if (nrow(try) == 0) { : argument has zero lenght 

我應該說數據庫有5000萬行,所以速度是一個問題在這裏(所以我嘗試使用lapply而不是for循環) 我不知道如何獲得正確的結果,這應該是像如下:

## Year Month Product Supermarket Price NewVar 
## 2015 1  67   1   10 1 
## 2015 1  65   1   11 1 
## 2015 1  69   1   15 1 
## 2015 2  65   2   20 1 
## 2015 2  67   2   25 1 
## 2015 2  67   3   15 0 
## 2015 2  69   3   12 0 

不知道如何解決整個問題。當使用lapply時,我得到了「正確」的答案,但是無法將結果粘貼到數據框的正確行中。

在此先感謝。

回答

0

我們可以在base R

df1$NewVar <- with(df1, ave(Product, Year, Month, Supermarket, 
             FUN= function(x) 65 %in% x)) 
df1$NewVar 
#[1] 1 1 1 1 1 0 0 
+1

謝謝,@akrun。只是要知道,爲什麼要包含產品?另外,在這個環境中做什麼(看幫助,並說它評估一個R表達式,美麗而簡單。 –

+0

@LeandroZipitria在第一個產品之後,所有其他變量都是分組變量,所以'x'是指產品'.''用於我們不需要使用'df1 $ Product','df1 $ Year'等,這會變得更羅嗦。 – akrun

+1

感謝您的時間。我學到了很多東西。 –

2

對於快速操作,請嘗試使用data.tabledplyr。隨着data.table,你可以簡單地創建由Year, Month and Supermarket變量組合邏輯檢查新的變量(假設你的原始數據幀被稱爲df):

library(data.table) 
setDT(df)[, NewVar := as.numeric(65 %in% Product), .(Year, Month, Supermarket)] 
df 
# Year Month Product Supermarket Price NewVar 
# 1: 2015  1  67   1 10  1 
# 2: 2015  1  65   1 11  1 
# 3: 2015  1  69   1 15  1 
# 4: 2015  2  65   2 20  1 
# 5: 2015  2  67   2 25  1 
# 6: 2015  2  67   3 15  0 
# 7: 2015  2  69   3 12  0 

或者相應地使用dplyrdf <- df %>% group_by(Year, Month, Supermarket) %>% mutate(NewVar = as.numeric(65 %in% Product))

+0

感謝@Psidom容易做到這一點!它工作出色。 –

+0

產品== 65?這看起來不正確。 NewVar包含67,69的「1」,但不包括所有這些值。 – mkearney

+0

@Mike OP正在試圖爲包含產品「65」的'Year,Month和Supermarket'標籤組而不僅僅是產品爲65的那些行。這基本上是對原始數據的總結,但是顯然OP想要保留數據的形狀,並添加標籤作爲一個新的列,這就是它是如何去這樣的。 – Psidom

1
## read data 
base <- c(2015, 1, 67, 1, 10, 
      2015, 1, 65, 1, 11, 
      2015, 1, 69, 1, 15, 
      2015, 2, 65, 2, 20, 
      2015, 2, 67, 2, 25, 
      2015, 2, 67, 3, 15, 
      2015, 2, 69, 3, 12) 
base <- data.frame(matrix(base, 7, byrow = TRUE)) 
names(base) <- c('Year', 'Month', 'Product', 'Supermarket', 'Price') 

製造一對夫婦改變功能。我改變對象以匹配輸入(x)和所指定的第三元件(因爲感興趣的列是3列)

## create function 
prueba <- function(x) ifelse(x[3] == 65, 1, 0) 

要應用此功能給每一行,使用具有1的應用()函數(用於行)apply(x, 1, function)

base$new_var <- apply(base, 1, prueba) 
base 
## Year Month Product Supermarket Price new_var 
## 1 2015  1  67   1 10  0 
## 2 2015  1  65   1 11  1 
## 3 2015  1  69   1 15  0 
## 4 2015  2  65   2 20  1 
## 5 2015  2  67   2 25  0 
## 6 2015  2  67   3 15  0 
## 7 2015  2  69   3 12  0 

您也可以創建一個新變量並有條件地向相關行輸入'1'。這是我做的方式:

base$new_var <- 0 
base$new_var[base$Product == 65] <- 1 
base 
## Year Month Product Supermarket Price new_var 
## 1 2015  1  67   1 10  0 
## 2 2015  1  65   1 11  1 
## 3 2015  1  69   1 15  0 
## 4 2015  2  65   2 20  1 
## 5 2015  2  67   2 25  0 
## 6 2015  2  67   3 15  0 
## 7 2015  2  69   3 12  0 
+0

感謝您的回答和新代碼。不是我正在尋找的東西(請參閱前一篇文章),但也很有用。最佳 –

相關問題