这实际上是关于R中值的引用字符类型的一系列问题。当我回忆起我认为哪些有趣且与此主题相关的任何其他相关问题时,会添加更多项目符号。为简化起见,我将在这里使用一些简单的随机例子来解释我的问题。希望这会有所帮助:
使用for循环构建一组数据集并希望在循环中输出一系列名为name_list = ("a", "b", "c", "d", "e", "f")
的列表中恢复名称的向量时,我们要将其定义为
for(i in 1:4){
a <- data[data$Year == 2010,]
b <- unique(data$Name)
c <- summarise(group_by(data,Year,Name), avg = mean(quantity))
...
f <- left_join(data,data1, by = c("Year", "Names)
}
是否有任何函数允许我使用function(name_list[1])
到function(name_list[6])
替换for循环中的a到f?这个问题也适用于在嵌入一大块代码的一些表/数据帧中使用列名创建列。 (as.name
和noquote
函数仅在引用向量/数据集时起作用,但在尝试将值分配给目标变量时不起作用,如果可能,任何人都可以分享为什么会发生这种情况?)
当我们从SQL或其他数据源中提取一些信息时,我们可能会将一些信息用逗号或其他一些分隔符分隔为一个变量。我们如何测试某些值是否是逗号分隔的值之一?请参阅以下示例:
1567 %in% c(1567,1456,123)
TRUE
a <- "c(1567,1456,123)"
noquote(a)
c(1567,1456,123)
1567 %in% noquote(a)
FALSE
1567 %in% list(noquote(a))
FALSE
b <- "1567,1456,123"
noquote(b)
1567,1456,123
1567 %in% noquote(strsplit(a,","))
FALSE
1567 %in% list(noquote(strsplit(a,",")))
FALSE
我知道为什么%in%
在这里不起作用,似乎R将1567,1456,123
作为一个元素。所以我用strsplit
分隔它们。但似乎它还没有奏效。想知道是否有任何方法可以让我们把字符串作为命令?
答案 0 :(得分:2)
如果你需要做的只是将逗号分隔的列表(如"1567,1456,123"
)转换为像c(1567, 1456, 123)
这样的R向量,你绝对不需要将它们包装在c(...)
中并尝试评估它们直接作为向量。您应该使用strsplit
来分割数据:
data_str <- "1567,1456,123"
data_vec <- as.integer(strsplit(string_data, ","))
stopifnot(1567 %in% data_vec)
请注意strsplit
会返回列表,因为它也可以是长度大于1的字符向量:
stopifnot(
all.equal(
list(c("a", "b"), c("x", "y")),
strsplit(c("a,b", "x,y"), ",")) == TRUE)
这使得它对SQL输出列的操作很有用:
| id | concatenated_field |
|----|--------------------|
| 1 | 5362,395,9000,7 |
| 2 | 319,75624,63 |
(etc.)
d <- data.frame(
id = c(1, 2),
concatenated_field = c("5362,395,9000,7", "319,75624,63"))
d$split_field <- strsplit(d$concatenated_field, ",")
sapply(d, class)
# id concatenated_field split_field
# "numeric" "character" "list"
d$split_field[[1]]
# [1] "5362" "395" "9000" "7"
或者,如果您正在阅读一个逗号分隔数据的大流,您可以使用scan
:
data_vec <- scan(
what = 0, # arcane way to say "expect numeric input"
sep = ",",
text = "1,2,3,4,5,6,7,8,9,10")
stopifnot(all.equal(data_vec, 1:10) == TRUE)
scan
比strsplit
更重要,并且可以处理更复杂的输入,例如带引号字段的数据:
weird_data <- scan(what="", sep=",", text='marvin,ruby,"joe,joseph",dean')
print(weird_data)
# [1] "marvin" "ruby" "joe,joseph" "dean"
如果您确实确定您需要能够接受并评估作为输入传递的R代码(这可能非常危险,因为这意味着您将执行任意未经验证的R代码),你可以用
r_code_string <- 'c("a", "b"), c("x", "y"))'
stopifnot(
all.equal(
c("a", "b"), c("x", "y")),
eval(parse(r_code_string))) == TRUE)
parse
将原始文本转换为未经评估的“表达式”,它以特殊R对象的形式表示R代码,eval
将表达式传递给解释器以供执行。
至于noquote
,它并不像你认为的那样做。它实际上并没有修改字符串,它只是为变量添加一个标志,以便它将打印而不带引号。您可以使用print(..., quote = FALSE)
来模拟此行为。