通过在 R 中传递 2 个变量来提取数据帧的单个值

Extract a single value of dataframe by passing 2 variables in R

我有一个查找 table,我想通过传递我的数据框的两个变量来提取此查找的单个值 table。一个变量匹配行 (P=P1),第二个变量匹配查找的列 table(A、B 和 C)。

这是我要完成的示例。

#lookup table
lookup_table <- data.table(P=c(2,4,6,8),
                           A=c(10:13),
                           B=c(20:23),
                           C=c(30,33))
#my data frame that I want to incorporate the lookup table values
my_data <- data.table(P1=c(4,6,8,2,6,8,4,2,6,4),
                      var1=c("B","C","A","B","C","A","A","B","C","A"))

我只想在我的数据框中添加相应的 lookup_table 值。

我导出了以下函数,但它不起作用。

get_from_lookup_table <- function(P,var1){
  lookup_table[P == P,..var1]
}

当我执行该函数并尝试将新列添加到我的数据框中时,所有值都显示为多列。

my_data$look_up_table_value <- get_from_lookup_table(my_data$P1,my_data$var1)
> my_data
    P1 var1 look_up_table_value
 1:  4    B      <multi-column>
 2:  6    C      <multi-column>
 3:  8    A      <multi-column>
 4:  2    B      <multi-column>
 5:  6    C      <multi-column>
 6:  8    A      <multi-column>
 7:  4    A      <multi-column>
 8:  2    B      <multi-column>
 9:  6    C      <multi-column>
10:  4    A      <multi-column>

看起来很简单,但我的数据框有超过 50000 行。

我们可以在 base R 中使用矢量化方法。将 data.table 转换为 data.frame,通过 match 使用 lookup_table 'P' 列和名称对数据集的列进行 row/column 索引lookup_table 创建一个 matrix 或 row/column 索引。用它来提取相应的值

df1 <- as.data.frame(my_data)
df1$look_up_table_value <- as.data.frame(lookup_table)[cbind(match(df1$P1, 
       lookup_table$P), match(df1$var1, names(lookup_table)))]

-输出

df1
   P1 var1 look_up_table_value
1   4    B                  21
2   6    C                  30
3   8    A                  13
4   2    B                  20
5   6    C                  30
6   8    A                  13
7   4    A                  11
8   2    B                  20
9   6    C                  30
10  4    A                  11

或者另一种选择是通过遍历序列

进行连接和 get 列的值
my_data[, look_up_table_value := my_data[, rn := seq_len(.N)][lookup_table, 
       on = .(P1 = P)][order(rn)][,get(var1), 1:nrow(my_data)]$V1]

mapply 允许使用您的原始代码:

get_from_lookup_table <- function(P,var1){
  unlist(mapply(function(row,col) lookup_table[P==row,..col],P,var1))
}

get_from_lookup_table(my_data$P1,my_data$var1)
# B  C  A  B  C  A  A  B  C  A 
# 21 30 13 20 30 13 11 20 30 11 


my_data$look_up_table_value <- get_from_lookup_table(my_data$P1,my_data$var1)

my_data

   P1 var1 look_up_table_value
 1:  4    B                  21
 2:  6    C                  30
 3:  8    A                  13
 4:  2    B                  20
 5:  6    C                  30
 6:  8    A                  13
 7:  4    A                  11
 8:  2    B                  20
 9:  6    C                  30
10:  4    A                  11

但是,这绝对没有效率:

a <- function() {
  df1 <- as.data.frame(my_data)
  df1$look_up_table_value <- as.data.frame(lookup_table)[cbind(match(df1$P1, 
                                                                     lookup_table$P), match(df1$var1, names(lookup_table)))]
  
}
w <- function() {my_data$look_up_table_value <- get_from_lookup_table(my_data$P1,my_data$var1)}

microbenchmark::microbenchmark(a(),w())

Unit: microseconds
 expr     min       lq      mean  median       uq     max neval
  a()   124.8   161.20   308.658   209.0   227.80  5563.0   100
  w() 11300.6 11973.35 13317.676 12340.1 13528.35 26613.7   100