如何通过列名应用ifelse函数?

时间:2015-09-01 16:11:02

标签: r function apply lapply sapply

我知道周围有许多类似的问题,但我担心无法理解这个问题,但很明显这很简单!

我正在尝试使用列名(而不是数字)编写一个简单的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

2 个答案:

答案 0 :(得分: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)或仅使用一元{ {1}},例如+

如果你想避免使用列名(我在帖子中真的不清楚),你可以构建+r来排除第一列。

答案 1 :(得分:3)

你几乎就在那里,这里有一个解决方案,使用apply over rows并使用all将测试向量转换为单个数字。

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