在数据框中每行选择一个单元格

krl*_*mlr 5 r matrix dataframe

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

> 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
Run Code Online (Sandbox Code Playgroud)

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

我已经考虑过转换d成矩阵,然后使用一维向量来解决矩阵元素.但后来我没有找到一种干净的方法来计算行和列索引的一维地址.

Rei*_*son 6

通过您的示例数据,并且仅使用前几行(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)
Run Code Online (Sandbox Code Playgroud)

首先,转换D成矩阵:

dmat <- data.matrix(D)
Run Code Online (Sandbox Code Playgroud)

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

(I - 1) * nrow(D) + seq_along(I)
Run Code Online (Sandbox Code Playgroud)

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

使用它,我们只需索引到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
Run Code Online (Sandbox Code Playgroud)

  • @user946850 和 Gavin (+1) —— 看起来 R 核心人员确实看到了其中的一些实用性,并将其(嗯,它的等效功能)添加到了当前的 R 开发中。(更多详细信息在我刚刚在下面添加的答案中)。 (2认同)

Jos*_*ien 4

如果您愿意首先将 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
Run Code Online (Sandbox Code Playgroud)

从 开始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
Run Code Online (Sandbox Code Playgroud)