使用字符串在dplyr(或基数R)中每行选择列

时间:2016-01-28 14:11:58

标签: r dplyr

我的列中填充了其他列名。我希望得到每个列名的值。

# three columns with values and one "key" column
library(dplyr)
data = data.frame(
  x = runif(10),
  y = runif(10),
  z = runif(10),
  key = sample(c('x', 'y', 'z'), 10, replace=TRUE)
)

# now get the value named in 'key'
data = data %>% mutate(value = VALUE_AT_COLUMN(key))

我很确定答案与mutate的懒惰eval版本有关,但我不能为我的生活弄明白。

任何帮助都将不胜感激。

4 个答案:

答案 0 :(得分:6)

我们可以尝试data.table。将'data.frame'转换为'data.table'(setDT(data)),按行序列分组,我们使用.SD对'key'指定的列进行子集化。

 library(data.table)
 setDT(data)[,  .SD[, key[[1L]], with=FALSE] ,1:nrow(data)]

或者,在按照前一种情况按行序列分组后,将“密钥”转换为get类(因为它character)后,其他选项为factor

 setDT(data)[, get(as.character(key)), 1:nrow(data)]

以下是do

的一个选项
 library(dplyr)
 data %>% 
    group_by(rn = row_number()) %>%
    do(data.frame(., value= .[[.$key]]))

答案 1 :(得分:5)

这是Base R解决方案:

data$value = diag(as.matrix(data[,data$key]))

答案 2 :(得分:5)

对于内存效率和快速解决方案,您应该通过执行连接来更新原始data.table,如下所示:

data[.(key2 = unique(key)), val := get(key2), on=c(key="key2"), by=.EACHI][]

对于每个key2,计算data$key中的匹配行。这些行将使用key2中包含的列中的值进行更新。例如,key2="x"与行1,2,6,8,10匹配。 data$x的相应值为data$x[c(1,2,6,8,10)]by=.EACHI确保为get(key2)的每个值执行表达式key2

由于此操作仅在唯一值上执行,因此应比在行中执行操作快得多。由于data.table是通过引用更新的,因此它应该具有很高的内存效率(这也有助于提高速度)。

答案 3 :(得分:4)

这肯定感觉应该有一个基本R解决方案,但我能做的最好的是tidyr,首先将数据转换为宽格式,然后过滤那些与所需匹配的观察键。

data %>%
  add_rownames("index") %>%
  gather(var, value, -index, -key) %>%
  filter(key == var)

基本的R解决方案几乎可以工作:

data[cbind(seq_along(data$key), data$key)]

对于给出的数据,它确实有效,但因为它使用矩阵,所以它有两个严重的问题。一个因素的顺序很重要,因为它只是强迫它,并按因子级别而不是列名称选择列。另一个是结果输出是character,而不是numeric,因为在转换为矩阵时,由于character列而选择了key类型。关键问题是

的矩阵行为没有data.frame类比
  

当用'''单个参数'i'索引数组时,可以是一个矩阵,其列数与'x'的维数相同;结果是一个向量,其元素对应于'i'每行中的索引集。

鉴于这些问题,我可能会使用tidyr解决方案,因为列可变地可选,这意味着它们可能代表同一可观察单元的不同观察结果。