r - 将变量作为列名传递给 dplyr?

标签 r dplyr

我有一个非常难看的数据集,它是一个关系数据库的平面文件。这里有一个最小的可重现示例:

df <- data.frame(col1 = c(letters[1:4],"c"), 
                  col1.p = 1:5, 
                  col2 = c("a","c","l","c","l"), 
                 col2.p = 6:10,
                  col3= letters[3:7],
                 col3.p = 11:20)

我需要能够识别具有“c”的“col#”的“.p”值。我之前关于 SO 的问题得到了第一部分:In R, find the column that contains a string in for each row .我正在提供上下文。

tmp <- which(projectdata=='Transmission and Distribution of Electricity', arr.ind=TRUE)
cnt <- ave(tmp[,"row"], tmp[,"row"], FUN=seq_along)
maxnames <- paste0("max",sequence(max(cnt)))
projectdata[maxnames] <- NA
projectdata[maxnames][cbind(tmp[,"row"],cnt)] <- names(projectdata)[tmp[,"col"]]
rm(tmp, cnt, maxnames)

这会产生一个如下所示的数据框:

df
   col1 col1.p col2 col2.p col3 col3.p max1
1     a      1    a      6    c     11 col3
2     b      2    c      7    d     12 col2
3     c      3    l      8    e     13 col1
4     d      4    c      9    f     14 col2
5     c      5    l     10    g     15 col1
6     a      1    a      6    c     16 col3
7     b      2    c      7    d     17 col2
8     c      3    l      8    e     18 col1
9     d      4    c      9    f     19 col2
10    c      5    l     10    g     20 col1

当我尝试获取与“max1”中的值相匹配的“.p”时,我不断出错。我认为方法是:

df %>%
   mutate(my.p = eval(as.name(paste0(max1,'.p'))))
Error: object 'col3.p' not found

显然,这行不通,所以我认为这可能类似于在函数中传递列名,我需要在其中使用“get”。那也没有用。

df %>%
   mutate(my.p = get(as.name(paste0(max1,'.p'))))
Error: invalid first argument
df %>%
   mutate(my.p = get(paste0(max1,'.p')))
Error: object 'col3.p' not found

我发现了一些可以消除此错误的方法,使用来自不同但相关问题的 data.table,此处:http://codereply.com/answer/7y2ra3/dplyr-error-object-found-using-rle-mutate.html .但是,它为我提供了每一行的“col3.p”。这是第一行的 max1,df$max1[1]

library('dplyr')
library('data.table') # must have the data.table package
df %>%
  tbl_dt(df) %>% 
  mutate(my.p = get(paste0(max1,'.p')))

Source: local data table [10 x 8]

   col1 col1.p col2 col2.p col3 col3.p max1 my.p
1     a      1    a      6    c     11 col3   11
2     b      2    c      7    d     12 col2   12
3     c      3    l      8    e     13 col1   13
4     d      4    c      9    f     14 col2   14
5     c      5    l     10    g     15 col1   15
6     a      1    a      6    c     16 col3   16
7     b      2    c      7    d     17 col2   17
8     c      3    l      8    e     18 col1   18
9     d      4    c      9    f     19 col2   19
10    c      5    l     10    g     20 col1   20

使用 lazyeval interp 方法(来自这个 SO: Hot to pass dynamic column names in dplyr into custom function? )对我不起作用。也许我实现不正确?

library(lazyeval)
library(dplyr)
df %>%
  mutate_(my.p = interp(~colp, colp = as.name(paste0(max1,'.p'))))

我得到一个错误:

Error in paste0(max1, ".p") : object 'max1' not found

理想情况下,我将使新列 my.p 等于基于 max1 中标识的列的适当 p

我可以用 ifelse 完成这一切,但我正在尝试用更少的代码来完成它,并使其适用于下一个丑陋的平面表。

最佳答案

我们可以用 data.table 来做到这一点。我们将 'data.frame' 转换为 'data.table' (setDT(df)),按行序列分组,我们获取 的值>粘贴输出,并将其分配(:=)到新列('my.p')。

library(data.table)
setDT(df)[, my.p:= get(paste0(max1, '.p')), 1:nrow(df)]
df
#    col1 col1.p col2 col2.p col3 col3.p max1 my.p
# 1:    a      1    a      6    c     11 col3   11
# 2:    b      2    c      7    d     12 col2    7
# 3:    c      3    l      8    e     13 col1    3
# 4:    d      4    c      9    f     14 col2    9
# 5:    c      5    l     10    g     15 col1    5
# 6:    a      1    a      6    c     16 col3   16
# 7:    b      2    c      7    d     17 col2    7
# 8:    c      3    l      8    e     18 col1    3
# 9:    d      4    c      9    f     19 col2    9
#10:    c      5    l     10    g     20 col1    5

关于r - 将变量作为列名传递给 dplyr?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32239778/

相关文章:

R - 重新排序直方图条形 - ggplot2

c++ - 包含 Rcpp.h 时出现 undefined reference 错误

r - 如何在检测到特定字符串后使用过滤器和 dplyr 删除数据帧行

r - 如何在没有变量的情况下以编程方式使用 dplyrcross()?

r - 为具有相同 'tidy' 格式和大小的不断变化的输入 csv 文件有效地创建 data.frames

r - 计算堆栈栅格中不同时间步长的平均值、中值和标准差

r - 选择具有多个不同值的组

r - 在不切断图形或丢失数据的情况下更改 ggplot 中的 y 轴限制

r - 在 R 中的两个数据帧(返回最大值的 VLOOKUP)中找到相对于另一个的最大值

r - 在 R 中使用 dplyr、tidyr、reshape2 进行复杂熔化