我试图用长度为2的向量替换2列中的每一行的值。更容易向您展示。
首先是一些数据。
set.seed(1234)
x<-data.frame(x=sample(c(0:3), 10, replace=T))
x$ab<-0 #column that will be replaced
x$cd<-0 #column that will be replaced
数据如下所示:
x ab cd
1 0 0 0
2 2 0 0
3 2 0 0
4 2 0 0
5 3 0 0
6 2 0 0
7 0 0 0
8 0 0 0
9 2 0 0
10 2 0 0
每当x = 2或x = 3时,我想要ab = 0且cd = 1。
我的尝试是这样的:
x[with(x, which(x==2|x==3)), c(2:3)] <- c(0,1)
没有预期结果:
x ab cd
1 0 0 0
2 2 0 1
3 2 1 0
4 2 0 1
5 3 1 0
6 2 0 1
7 0 0 0
8 0 0 0
9 2 1 0
10 2 0 1
你能帮助我吗?
答案 0 :(得分:8)
它无法正常工作的原因是因为R在列主要布局中存储矩阵和数组。当你为较长的数组分配一个较短的数组时,R循环通过较短的数组。例如,如果你有
x<-rep(0,20)
x[1:10]<-c(2,3)
然后你最终得到了
[1] 2 3 2 3 2 3 2 3 2 3 0 0 0 0 0 0 0 0 0 0
在您的情况下发生的事情是,通过循环遍历向量c(0,1)
,在列中方式填充x等于2或3的子数组。我不知道有什么简单的方法可以改变这种行为。
这里最简单的方法可能就是一次只填写一列。或者,你可以这样做:
indices<-with(x, which(x==2|x==3))
x[indices,c(2,3)]<-rep(c(0,1),each=length(indices))
答案 1 :(得分:7)
另一种选择:使用data.table,这是一个单行:
require(data.table)
DT <- data.table(x)
DT[x%in%2:3,`:=`(ab=0,cd=1)]
原始答案:您可以传递行列对矩阵:
ijs <- expand.grid(with(x, which(x==2|x==3)),c(2:3))
ijs <- ijs[order(ijs$Var1),]
x[as.matrix(ijs)] <- c(0,1)
产生
x ab cd
1 0 0 0
2 2 0 1
3 2 0 1
4 2 0 1
5 3 0 1
6 2 0 1
7 0 0 0
8 0 0 0
9 2 0 1
10 2 0 1
我的原始答案适用于我的电脑,但不适用于评论者。
答案 2 :(得分:2)
针对多列和多值进行广义化:
mycol<-as.list(names(x)[-1])
myvalue<-as.list(c(0,1))
kk<-Map(function(y,z) list(x[x[,1] %in% c(2,3),y]<-z,x),mycol, myvalue)
myresult<-data.frame(kk[[2]][[2]])
x ab cd
1 1 0 0
2 1 0 0
3 0 0 0
4 0 0 0
5 0 0 0
6 3 0 1
7 2 0 1
8 3 0 1
9 3 0 1
10 0 0 0
答案 3 :(得分:1)
您可以使用ifelse
:
> set.seed(1234)
> dat<-data.frame(x=sample(c(0:3), 10, replace=T))
> dat$ab <- 0
> dat$cd <- ifelse(dat$x==2 | dat$x==3, 1, 0)
x ab cd
1 0 0 0
2 2 0 1
3 2 0 1
4 2 0 1
5 3 0 1
6 2 0 1
7 0 0 0
8 0 0 0
9 2 0 1
10 2 0 1
答案 4 :(得分:0)
x$ab[x$x==2 | x$x==3] <- 0
x$cd[x$x==2 | x$x==3] <- 1
修改
这是一种适用于大量列的一般方法。您只需创建一个希望用于每列的替换值的向量。
set.seed(1234)
y<-data.frame(x=sample(c(0:3), 10, replace=T))
y$ab<-4 #column that will be replaced
y$cd<-2 #column that will be replaced
y$ef<-0 #column that will be replaced
y
# x ab cd ef
#1 0 4 2 0
#2 2 4 2 0
#3 2 4 2 0
#4 2 4 2 0
#5 3 4 2 0
#6 2 4 2 0
#7 0 4 2 0
#8 0 4 2 0
#9 2 4 2 0
#10 2 4 2 0
replacement.values <- c(10,20,30)
y2 <- y
y2[,2:ncol(y)] <- sapply(2:ncol(y), function(j) {
apply(y, 1, function(i) {
ifelse((i[1] %in% c(2,3)), replacement.values[j-1], i[j])
})
})
y2
# x ab cd ef
#1 0 4 2 0
#2 2 10 20 30
#3 2 10 20 30
#4 2 10 20 30
#5 3 10 20 30
#6 2 10 20 30
#7 0 4 2 0
#8 0 4 2 0
#9 2 10 20 30
#10 2 10 20 30
答案 5 :(得分:0)
怎么样?
x[x$x%in%c(2,3),c(2,3)]=matrix(rep(c(0,1),sum(x$x%in%c(2,3))),ncol=2,byrow=TRUE)