2015-09-01 58 views
1

我知道周圍有很多類似的問題,但恐怕無法繞開這個特定的問題,但顯然它非常簡單!如何按列名應用ifelse函數?

我想寫一個簡單的ifelse函數,通過使用列名稱(而不是數字)應用於數據框中的一系列列。我試圖做的是創建一個單獨的u_all變量,如下所示,而不重複輸入列名稱。

dat <- data.frame(id=c(1:20),u1 = sample(c(0:1),20,replace=T) , u2 = sample(c(0:1),20,replace=T) , u3 = sample(c(0:1),20,replace=T)) 
dat<-within(dat,u_all<-ifelse (u1==1 | u2==1 |u3==1,1,0)) 
dat 

我試過的apply很多變種,但顯然我不是在正確的軌道上那些分組功能複製ifelse功能上的每一列分別。

dat2 <- data.frame(id=c(1:20),u1 = sample(c(0:1),20,replace=T) , u2 = sample(c(0:1),20,replace=T) , u3 = sample(c(0:1),20,replace=T)) 

dat2<-cbind(dat2,sapply(dat2[,grepl("^u\\d{1,}",colnames(dat2))], 
           function(x){ u_all<-ifelse(x==1 & !is.na(x),1,0)})) 

dat2 
+1

當試圖使用存儲在變量中的列名時,諸如'$','with','within','subset'等的快捷鍵不是**你的朋友。只使用'[''而且事情效果更好。 – Gregor

+0

@格雷戈謝謝!但我可以問爲什麼?你的意思是,例如,我應該避免使用快捷方式'$'(如'dat $ u1')並使用'dat [,2]'來代替? – Eva

+1

如果'「u2」'是一個列的名字,'dat $ u2'就可以了。但是如果'u2 < - 「mpg」','mtcars $ u2'將不起作用,因爲'$'不會評估'u2',它會查找一個名爲'「u2」'的列。但是如果'u2 < - 「mpg」','mtcars [,u2]'**將會工作,就像'mtcars [,'mpg「]'一樣。例如,參見'fortunes :: fortune(343)','fortunes :: fortune(312)'和'subset'中的警告......應該也可以包含在'with with'中。 – Gregor

回答

5

這條線從OP

dat<-within(dat,u_all<-ifelse (u1==1 | u2==1 |u3==1,1,0)) 

可以代替寫成

dat$u_all <- +Reduce("|", dat[, c("u1", "u2", "u3")]) 

它是如何工作的,在中間對象方面:

  • D = dat[, c("u1", "u2", "u3")]使用列的名稱來對數據框進行子集化。
  • r = Reduce("|", D)通過在每對列之間放置|來摺疊數據。結果是一個邏輯(TRUE/FALSE)向量。
  • r轉換爲0/1整數向量,您可以使用ifelse(r,1L,0L)as.integer(r)(因爲TRUE/FALSE轉換到1/0默認)或只有一元+,像+r

如果您使用的列名(這真的不是很清楚,我從後)要避免,您可以構建D = dat[-1]排除第一列代替。

+2

非常感謝!對不起,不清楚。我沒有試圖避免列名,相反,我想使用列名,但不想逐個輸入,因爲列數很多。所以我在我的腳本中將你的代碼編輯爲'dat $ u_all < - + Reduce(「|」,dat [,grepl(「^ u \\ d {1,}」,colnames(dat))])''。工作非常好! – Eva

3

你幾乎在那裏,這裏有一個解決方案,使用apply over rows並使用all來將測試向量轉換爲單個數字。

dat2$u_all <- apply(dat2[,-1], MARGIN=1, FUN=function(x){ 
    any(x==1)&all(!is.na(x))*1 
} 
) 
+0

謝謝!但這看起來不正確。有了這個代碼,只有當所有三個變量(u1,u2和u3)都是1時,u_all才取值1. – Eva

+1

糟糕,抱歉。編輯爲「任何」。假設你想測試是否所有值都沒有丟失,不確定你希望如何處理這些值。 – Heroka