5

我有一个向量告诉我,对于日期框架中的每一行,应该更新该行中的值的列索引。

> set.seed(12008); n <- 10000; d <- data.frame(c1=1:n, c2=2*(1:n), c3=3*(1:n))
> i <- sample.int(3, n, replace=TRUE)
> head(d); head(i)
  c1 c2 c3
1  1  2  3
2  2  4  6
3  3  6  9
4  4  8 12
5  5 10 15
6  6 12 18
[1] 3 2 2 3 2 1

这意味着对于第 1 行和第 4 行,应更新 c3;对于第 2、3 和 5 行,应更新 c2(除其他外)。在 R 中使用矢量化操作(即没有apply和朋友)实现这一目标的最简洁方法是什么?编辑:而且,如果可能的话,没有 R 循环?

我曾考虑过转换d为矩阵,然后使用一维向量寻址矩阵元素。但是我还没有找到一种从行索引和列索引计算一维地址的干净方法。

4

3 回答 3

4

使用您的示例数据,并且仅使用前几行(DI以下),您可以通过矩阵轻松地做您想的事情。

set.seed(12008)
n <- 10000
d <- data.frame(c1=1:n, c2=2*(1:n), c3=3*(1:n))
i <- sample.int(3, n, replace=TRUE)
## just work with small subset
D <- head(d)
I <- head(i)

首先,转换D成矩阵:

dmat <- data.matrix(D)

接下来计算对应于由 指示的行和列的矩阵的向量表示的索引I。为此,很容易生成行索引以及列索引(由 给出Iseq_along(I),在这个简单的例子中是向量1:6。要计算向量索引,我们可以使用:

(I - 1) * nrow(D) + seq_along(I)

其中第一部分 ( (I - 1) * nrow(D)) 为我们提供了行数的正确倍数(此处为 6)来索引I第 th 列的开头。然后我们添加行索引以获得第Ith 列中第 n 个元素的索引。

使用这个我们只是索引到dmatusing "[",把它当作一个向量。"["( )的替换版本"[<-"允许我们在一行中进行替换。在这里,我将指示的元素替换为NA,以便更容易看到识别出正确的元素:

> dmat
  c1 c2 c3
1  1  2  3
2  2  4  6
3  3  6  9
4  4  8 12
5  5 10 15
6  6 12 18
> dmat[(I - 1) * nrow(D) + seq_along(I)] <- NA
> dmat
  c1 c2 c3
1  1  2 NA
2  2 NA  6
3  3 NA  9
4  4  8 NA
5  5 NA 15
6 NA 12 18
于 2012-06-05T10:47:56.923 回答
3

这是一种方法:

d[which(i == 1), "c1"] <- "one"
d[which(i == 2), "c2"] <- "two"
d[which(i == 3), "c3"] <- "three"

   c1  c2    c3
1   1   2 three
2   2 two     6
3   3 two     9
4   4   8 three
5   5 two    15
6 one  12    18
于 2012-06-05T09:34:03.540 回答
3

如果您愿意先将 data.frame 转换为矩阵,则可以使用两列矩阵索引要替换的元素。(从 开始R-2.16.0,可以直接使用 data.frames。)索引矩阵的第一列应该有行索引,第二列应该有列索引。

这是一个例子:

## Create a subset of the your data
set.seed(12008); n  <- 6 
D  <- data.frame(c1=1:n, c2=2*(1:n), c3=3*(1:n))
i <- seq_len(nrow(D))            # vector of row indices
j <- sample(3, n, replace=TRUE)  # vector of column indices 
ij <- cbind(i, j)                # a 2-column matrix to index a 2-D array 
                                 # (This extends smoothly to higher-D arrays.)  

## Convert it to a matrix    
Dmat <- as.matrix(D)

## Replace the elements indexed by 'ij'
Dmat[ij] <- NA
Dmat
#      c1 c2 c3
# [1,]  1  2 NA
# [2,]  2 NA  6
# [3,]  3 NA  9
# [4,]  4  8 NA
# [5,]  5 NA 15
# [6,] NA 12 18

从 开始R-2.16.0,您将能够对数据帧使用相同的语法(即无需先将数据帧转换为矩阵)。

R-devel NEWS文件中:

现在支持通过两列数字索引对数据帧进行矩阵索引以进行替换和提取。

使用当前R-devel快照,如下所示:

D[ij] <- NA
D
#   c1 c2 c3
# 1  1  2 NA
# 2  2 NA  6
# 3  3 NA  9
# 4  4  8 NA
# 5  5 NA 15
# 6 NA 12 18
于 2012-06-07T16:36:56.770 回答