我试过搜索,但没有找到这个问题的答案.
我正在尝试在dplyr中使用select语句,但在尝试发送字符串时遇到问题.我的问题是,我怎么告诉select()它看到的字符串是数据框中的列名?
这样工作正常
select(df.main.scaled, var1, var3)
select(df.main.scaled, var2, var4)
Run Code Online (Sandbox Code Playgroud)
但这不起作用:
select(df.main.scaled, names.gens[i,1], names.gens[i,2])
Run Code Online (Sandbox Code Playgroud)
哪里
> names.genx <- c("var1","var2")
> names.geny <- c("var3","var4")
> names.gens <- cbind(names.genx, names.geny)
> names.gens
names.genx names.geny
[1,] "var1" "var3"
[2,] "var2" "var4"
Run Code Online (Sandbox Code Playgroud)
要清楚,names.gens中的所有字符串都是数据框中的列名.
谢谢.
sli*_*izb 50
在较新版本dplyr的,这是可能在select与one_of,在
my_cols <- c('mpg', 'disp')
mtcars %>% select(one_of(my_cols))
Run Code Online (Sandbox Code Playgroud)
jpm*_*iaz 33
Select似乎与列索引(dplyr 0.2)一起使用,因此只需将您想要的名称与其索引匹配,并使用它们来选择列.
myCols <- c("mpg","disp")
colNums <- match(myCols,names(mtcars))
mtcars %>% select(colNums)
Run Code Online (Sandbox Code Playgroud)
nau*_*101 10
您可以使用get()在当前环境中获取由字符串命名的对象.所以:
R> iris %>% select(Species, Petal.Length) %>% head(3)
Species Petal.Length
1 setosa 1.4
2 setosa 1.4
3 setosa 1.3
R> iris %>% select('Species', 'Petal.Length') %>% head(3)
Error in abs(ind[ind < 0]) :
non-numeric argument to mathematical function
R> iris %>% select(get('Species'), get('Petal.Length')) %>% head(3)
Species Petal.Length
1 setosa 1.4
2 setosa 1.4
3 setosa 1.3
R> s <- 'Species'
R> p <- 'Petal.Length'
R> iris %>% select(get(s), get(p)) %>% head(3)
Species Petal.Length
1 setosa 1.4
2 setosa 1.4
3 setosa 1.3
Run Code Online (Sandbox Code Playgroud)
Rob*_*inL 10
[编辑 - 下面的一些内容已经过时,发布了dplyr 0.7 - 请看这里 ]
问题是标准评估和非标准评估之间的区别.
tl; dnr:你可以使用'标准评估'对应的dplyr::select,即dplyr::select_.
这允许您提供列名作为包含字符串的变量:
dplyr::select_(df.main.scaled, names.gens[i,1], names.gens[i,2])
这里有更多细节试图解释它是如何工作的:
非标准评估是以非标准方式评估代码.通常,这意味着在评估表达式之前捕获它们,并在不同的环境(上下文/范围)中将它们评估为正常.当您提供dplyr::select不带引号的列名时,dplyr使用非标准评估将它们解释为列.
假设我们有以下数据框:
df <- tibble::data_frame(a = 1:5, b = 6:10, c = 11:15, d = 16:20)
Run Code Online (Sandbox Code Playgroud)
select语句的一个简单示例如下:
r <- dplyr::select(df, a, b)
Run Code Online (Sandbox Code Playgroud)
这是NSE的一个示例,因为a和b不是全局环境中存在的变量.不是在全局命名空间中搜索a和b,而是dplyr::select指示R在数据帧的上下文中搜索变量a和b df.您可以将环境视为列表,将a和b视为键.所以以下有点像告诉R查找df$a和df$b
R中的函数参数是未立即求值的promise.它们可以作为表达式捕获,然后在不同的环境中运行.
如果我们知道我们想要提前选择列a,这很好b.但是,如果这些列事先未知,并保存在变量中,该怎么办呢?
columns_to_select <- c("a", "b")
Run Code Online (Sandbox Code Playgroud)
以下不起作用:
dplyr::select(df, columns_to_select)
Run Code Online (Sandbox Code Playgroud)
此错误告诉我们数据框中没有名为"columns_to_select"的列.该参数columns_to_select已在数据框的上下文中进行了评估,因此R尝试执行类似的操作df$columns_to_select,并发现该列不存在.
我们如何解决这个问题?
Tidyverse功能总是提供一个"逃生舱",让您可以绕过这个限制.该dplyr小品说:"在使用NSE dplyr每个功能也都有使用SE版本.SE版本的名称始终是NSE名称,末尾带有_.
这是什么意思?
我们可能会尝试以下方法,但我们发现它不起作用:
# Does not work
r <-dplyr::select_(df, columns_to_select)
Run Code Online (Sandbox Code Playgroud)
与将参数捕获columns_to_select到select_函数并将其解释为列名称columns_to_select相反,以标准方式计算,解析为c("a", "b").
这就是我们想要的,除了每个参数select_都是一个列,我们刚刚提供了一个长度为2的字符向量来表示一个列.
因此,上面的代码返回一个包含单列a的tibble,这不是我们想要的.(只使用第一个元素 - "a"在字符向量中,忽略其他所有元素).
这个问题的一个解决方案如下,但它假设columns_to_select包含两个元素:
col1 <- columns_to_select[1]
col2 <- columns_to_select[2]
r <- dplyr::select_(df,col1, col2)
Run Code Online (Sandbox Code Playgroud)
我们如何将此概括为columns_to_select可能具有任意数量元素的情况?
解决方案是使用可选.dots参数.
dplyr::select_(df, .dots=columns_to_select)
Run Code Online (Sandbox Code Playgroud)
这有一些解释
在R中,...构造允许创建具有可变(任意)数量的参数的函数.它在函数中...可用,并允许函数体访问所有参数.另见这里.
一个非常简单的例子如下:
addition <- function(...) {
args <- list(...)
sum(unlist(args))
}
r <- addition(1,2,3)
Run Code Online (Sandbox Code Playgroud)
但是,这并没有立即帮助我们.它实际上已经在select_函数中实现,只是使我们能够提供任意数量的列名作为参数,例如select_(df, "a", "b", "c", "d").
我们需要的是类似于一种机制...,但可以让我们像传递... 到函数作为一个参数.这正是这样.dots做的.
请注意,这.dots不是由提供的select,因为它旨在以交互方式使用.
我碰到了这个,我想我应该提到这已经在较新版本的dplyr中解决了.
myTest = data_frame(
var1 = 1,
var2 = 2,
var3 = 3,
var4 = 4)
i = 1
myTest %>%
select_(.dots =
c(names.gens[i,1], names.gens[i,2]) %>% unname)
Run Code Online (Sandbox Code Playgroud)
对于字符串你可以这样做
my_cols <- c("mpg", "disp")
mtcars %>% select(!!!my_cols)
Run Code Online (Sandbox Code Playgroud)
虽然,我认为避免使用字符串并做可能是更好的做法
my_cols <- quos(mpg, disp)
mtcars %>% select(!!!my_cols)
Run Code Online (Sandbox Code Playgroud)
Kir*_*rkH -6
我通过反复试验弄清楚了。如果有人好奇,可以这样做:
lapply(names.gens, as.name)
select(df.main.scaled, eval(names.gens[[i]]), eval(names.gens[[i+someindex]]))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
30326 次 |
| 最近记录: |