一些示例数据:
ID S1Qual S2Qual S3Qual S1 S2 S3
1 1 0 1 7 8 7
2 1 1 1 6 6 8
3 0 1 1 7 8 8
...
S1Qual,S2Qual和S3Qual分别表示S1PS,S2PS和S3PS的质量。如果[n, S1Qual] == 1
,我想保留[n, S1PS]
;如果[n,S1Qual] == 0
,我想设置[n,S1PS] == NA
。
我有以下代码:
n <- 1
while (n <= number.of.rows) {
if (data$S1Qual[n] == 0) {data$S1[n] <- NA}
if (data$S2Qual[n] == 0) {data$S2[n] <- NA}
if (data$S3Qual[n] == 0) {data$S3[n] <- NA}
n <- n+1
}
这就是我想要的,但我希望有一种更有效/简洁的方式(在实际数据框中,这些S / SQual对中有三个以上)。搜索引导我ifelse()
和apply()
,这两者看起来很接近但不太适合我想要的东西,除非我认为错了。
有什么想法吗?
答案 0 :(得分:2)
使用此:
cols <- paste0("S", 1:3)
data[,cols][data[,paste0(cols,"Qual")]==0] <- NA
注意:更改向量1:3
以匹配您的实际列数。
答案 1 :(得分:1)
如果你保持简单,我发现理解R代码会更容易。它帮助了我忘记一切的未来。
你可以制作副本,并对任何等于零的项目做一个简单的替换(这是费迪南德所做的......他更聪明):
data1 <- data[,c(2:4)]
data2 <- data[,c(5:7)]
data2[data1==0] <- NA
data[,c(5:7)] <- data2
编辑说明:
前两行创建相等尺寸的数据框。由于它们具有相同的尺寸,因此您可以使用data1
中的索引来引用data2
。
神奇发生在第三行(技术上称为过滤)。如果data1
中的元素为0,则返回TRUE,否则返回FALSE。第三行说“如果data1
中的元素为0,则从data2
返回该索引。”例如,使用上面的示例数据,如果data1[1,2]
处的元素为零(它是),则将NA分配给data2[1,2]
。
最后一行用新的3x3子矩阵替换旧的3x3子矩阵。
答案 2 :(得分:0)
mydata<-mtcars[1:10,1:4]
mydata
mpg cyl disp hp
Mazda RX4 21.0 6 160.0 110
Mazda RX4 Wag 21.0 6 160.0 110
Datsun 710 22.8 4 108.0 93
Hornet 4 Drive 21.4 6 258.0 110
Hornet Sportabout 18.7 8 360.0 175
Valiant 18.1 6 225.0 105
Duster 360 14.3 8 360.0 245
Merc 240D 24.4 4 146.7 62
Merc 230 22.8 4 140.8 95
Merc 280 19.2 6 167.6 123
fi<-as.list(names(mydata)[1:2]) # first two columns to be used as base
se<-as.list(names(mydata)[3:4]) # second two columns which will be replaced based on first two cols
kk<-Map(function(x,y) mydata[[y]]<-ifelse(mydata[[x]]>4,1,mydata[[y]]),fi,se) # for your example replace >4 with `==0` and 1 with NA
ll<-t(do.call(rbind,kk))
mydata[,3:4]<-ll
MYDATA
mpg cyl disp hp
Mazda RX4 21.0 6 1 1
Mazda RX4 Wag 21.0 6 1 1
Datsun 710 22.8 4 1 93
Hornet 4 Drive 21.4 6 1 1
Hornet Sportabout 18.7 8 1 1
Valiant 18.1 6 1 1
Duster 360 14.3 8 1 1
Merc 240D 24.4 4 1 62
Merc 230 22.8 4 1 95
Merc 280 19.2 6 1 1
对于您的数据:
fi<-as.list(names(mydata)[1:3]) # first three columns to be used as base
se<-as.list(names(mydata)[4:6]) # second three columns which will be replaced based on first three cols
kk<-Map(function(x,y) mydata[[y]]<-ifelse(mydata[[x]]==0,NA,mydata[[y]]),fi,se)
ll<-t(do.call(rbind,kk))
mydata[,4:6]<-ll