5

我正在尝试用长度为 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

你能帮助我吗?

4

6 回答 6

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

在您的情况下发生的情况是 x 等于 2 或 3 的子数组正在通过遍历 vector 逐列填充c(0,1)。我不知道有什么简单的方法可以改变这种行为。

可能在这里做的最简单的事情就是一次填写一列。或者,您可以执行以下操作:

indices<-with(x, which(x==2|x==3))
x[indices,c(2,3)]<-rep(c(0,1),each=length(indices))
于 2013-09-24T16:39:11.153 回答
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

我的原始答案适用于我的电脑,但不是评论者的。

于 2013-09-24T16:32:39.503 回答
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
于 2013-09-24T16:46:14.623 回答
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
于 2013-09-24T16:28:45.440 回答
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
于 2013-09-24T16:27:24.090 回答
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)
于 2013-09-24T17:28:56.743 回答