10

考虑以下数据框:

TEST <- structure(list(Value = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), 
  Select = structure(c(2L, 1L, 3L, 2L, 2L, 1L, 1L,
  2L, 1L, 1L, 3L, 3L), .Label = c("A", "B", "C"), class = "factor"),
  A = c(5L, 5L, 4L, 3L, 4L, 3L, 5L, 3L, 3L, 4L, 5L, 4L), 
  B = c(10L, 8L, 7L, 6L, 3L, 8L, 8L, 7L, 8L, 9L, 11L, 8L), 
  C = c(0L, 1L, 3L, 2L, 0L, 3L, 0L, 2L, 0L, 1L, 1L, 0L)), 
  .Names = c("Value", "Select", "A", "B", "C"), 
  row.names = c(NA, -12L), 
  class = "data.frame")

我想根据 Select 列从列 A、B 和 C 的集合中逐行有效地分配 Value 列。

例如,在第 1 行中,我希望 Value 等于 B 列中的元素 - 即 Value[1]=10。

我目前的方法是使用 for 循环:

for( idx in 1:nrow(TEST) ) {
  TEST$Value[idx] <- TEST[ idx, as.character(TEST$Select[idx]) ]
}

这会产生所需的输出:

    值选择 ABC
 1 10 乙 5 10 0
 2 5 一个 5 8 1
 3 3 C 4 7 3
 4 6 乙 3 6 2
 5 3 乙 4 3 0
 6 3 一个 3 8 3
 7 5 一个 5 8 0
 8 7 乙 3 7 2
 9 3 一个 3 8 0
 10 4 一个 4 9 1
 11 1 C 5 11 1
 12 0 C 4 8 0

有没有更有效或替代的方法来做到这一点?我觉得这是某种合并()或表连接类型的操作。

PS我不太确定如何描述这个操作——也欢迎任何关于更好问题/描述的建议。

4

1 回答 1

10

我会使用矩阵索引match. 这种方法是矢量化的,因此比fororapply循环给你的速度要快得多:

L <- c("A", "B", "C")
TEST$Value <- TEST[L][cbind(seq_len(nrow(TEST)), match(TEST$Select, L))]

如果您不熟悉矩阵索引,请参阅以下文档?"["

第三种索引形式是通过一个数字矩阵,每个维度有一列:索引矩阵的每一行然后选择数组的单个元素,结果是一个向量

于 2013-08-05T11:21:51.630 回答