【问题标题】:Getting strings recognized as variable names in R在 R 中将字符串识别为变量名
【发布时间】:2012-02-21 20:12:18
【问题描述】:

相关:Strings as variable references in R
可能相关:Concatenate expressions to subset a dataframe


我已根据评论请求简化了问题。这里有一些示例数据。

dat <- data.frame(num=1:10,sq=(1:10)^2,cu=(1:10)^3)
set1 <- subset(dat,num>5)
set2 <- subset(dat,num<=5)

现在,我想根据这些制作一个气泡图。我有一个更复杂的数据集,包含 3 种以上的颜色和复杂的子集,但我做了这样的事情:

symbols(set1$sq,set1$cu,circles=set1$num,bg="red")
symbols(set2$sq,set2$cu,circles=set2$num,bg="blue",add=T)

我想做一个这样的 for 循环:

colors <- c("red","blue")
sets <- c("set1","set2")
vars <- c("sq","cu","num")

for (i in 1:length(sets)) {
   symbols(sets[[i]][,sq],sets[[i]][,cu],circles=sets[[i]][,num],
   bg=colors[[i]],add=T)
}    

我知道您可以评估一个变量来指定列(例如 var="cu"; set1[,var];我想知道如何获取一个变量来指定 data.frame 本身(以及另一个来评估列)。


更新:在 r-bloggers 上遇到this post,其中有这个例子:

x <- 42
eval(parse(text = "x"))
[1] 42

我现在可以做这样的事情了:

eval(parse(text=paste(set[[1]],"$",var1,sep="")))

在摆弄这一点时,我发现以下内容不等价很有趣:

vars <- data.frame("var1","var2")
eval(parse(text=paste(set[[1]],"$",var1,sep="")))
eval(parse(text=paste(set[[1]],"[,vars[[1]]]",sep="")))

我实际上必须这样做:

eval(parse(text=paste(set[[1]],"[,as.character(vars[[1]])]",sep="")))

Update2:以上内容可用于输出值...但不适用于尝试绘图。我做不到:

for (i in 1:length(set)) {
symbols(eval(parse(text=paste(set[[i]],"$",var1,sep=""))),
       eval(parse(text=paste(set[[i]],"$",var2,sep=""))),
       circles=paste(set[[i]],".","circles",sep=""),
       fg="white",bg=colors[[i]],add=T)
}

我收到invalid symbol coordinates。我检查了 set[[1]] 的类,这是一个因素。如果我这样做is.numeric(as.numeric(set[[1]])),我会得到TRUE。即使我在eval 语句之前添加了上面的内容,我仍然会收到错误消息。不过奇怪的是,我可以这样做:

set.xvars <- as.numeric(eval(parse(text=paste(set[[i]],"$",var1,sep=""))))
set.yvars <- as.numeric(eval(parse(text=paste(set[[i]],"$",var2,sep=""))))
symbols(xvars,yvars,circles=data$var3)

为什么存储为变量和在符号函数中执行时会有不同的行为?

【问题讨论】:

  • 你有没有机会用实际问题重写你的问题?标题中有一个,但没有简明扼要地说明您正在尝试做什么。
  • 如果你用dput给我们一些示例数据也会很有帮助。
  • @Maiasaura:如果我的修订更清晰,请告诉我。我真的不认为数据是必要的,但如果你真的需要它,我会想出一些例子。
  • var1=42; foo="var1"; get(foo); 是另一种获取以字符串命名的变量的方法。
  • @Maiasaura:是的,但我想要数据框的列。我知道我可以做你做的事,但做 get("data$var1") 是行不通的。

标签: r variables string-concatenation


【解决方案1】:

您找到了一个答案,即 eval(parse()) 。您还可以调查do.call(),这通常更容易实现。请记住有用的 as.name() 工具,用于将字符串转换为变量名。

【讨论】:

  • 在尝试将粘贴字符串转换为变量时,eval(as.name(paste())) 为我工作,谢谢!
  • 我有一个复杂的结构(myList 的许多数据帧列表,例如 myDF1myDF2 等)和 eval(parse(text=paste0(myList$myDF, "index"))) 为我工作。谢谢!
  • eval(as.name(CHARACTER_HERE)) 为我工作,希望这对某人有所帮助。
【解决方案2】:

标题中问题的基本答案是 eval(as.symbol(variable_name_as_string)),正如 Josh O'Brien 使用的那样。例如

var.name = "x"
assign(var.name, 5)
eval(as.symbol(var.name)) # outputs 5

或者更简单地说:

get(var.name) # 5

【讨论】:

    【解决方案3】:

    没有任何示例数据,真的很难准确地知道你想要什么。例如,我完全无法预测您的对象 set(或者是 sets)的样子。

    也就是说,以下是否有帮助?

    set1 <- data.frame(x = 4:6, y = 6:4, z = c(1, 3, 5))
    
    plot(1:10, type="n")
    XX <- "set1"
    with(eval(as.symbol(XX)), symbols(x, y, circles = z, add=TRUE))
    

    编辑

    现在我看到了你的真正任务,这里有一个单行代码,可以做你想做的一切,而不需要任何 for() 循环:

    with(dat, symbols(sq, cu, circles = num,
                      bg = c("red", "blue")[(num>5) + 1]))
    

    可能会感到奇怪的代码是指定背景颜色的代码。试试这两行代码,看看它是如何工作的:

    c(TRUE, FALSE) + 1
    # [1] 2 1
    c("red", "blue")[c(F, F, T, T) + 1]
    # [1] "red"  "red"  "blue" "blue"
    

    【讨论】:

    • 我为您添加了一个示例数据集,但您的示例有效。我不熟悉with 的使用——似乎它为后续变量名提供了一个框架。我是这样成功使用的:for (i in 1:length(sets)) { with(eval(as.symbol(sets[[i]])), symbols(sq,cu,circles=num,bg=colors[[i]],add=T))Thanks!
    • @Hendy -- 很高兴听到。我还刚刚添加了一个单线,它可以让您在不使用所有subset()for() 循环的情况下制作整个情节。祝你好运!
    【解决方案4】:

    如果要使用字符串作为变量名,可以使用assign:

    var1="string_name"
    
    assign(var1, c(5,4,5,6,7))
    
    string_name 
    
    [1] 5 4 5 6 7
    

    【讨论】:

      【解决方案5】:

      没有必要对数据进行子集化并将它们组合回来。循环也是如此,因为这些操作是矢量化的。从您之前的编辑中,我猜您正在做所有这些来制作气泡图。如果这是正确的,也许下面的示例会对您有所帮助。如果这太离谱了,我可以删除答案。

      library(ggplot2)
      # let's look at the included dataset named trees.
      # ?trees for a description
      data(trees)
      ggplot(trees,aes(Height,Volume)) + geom_point(aes(size=Girth))
      # Great, now how do we color the bubbles by groups?
      # For this example, I'll divide Volume into three groups: lo, med, high
      trees$set[trees$Volume<=22.7]="lo"
      trees$set[trees$Volume>22.7 & trees$Volume<=45.4]="med"
      trees$set[trees$Volume>45.4]="high"
      
      ggplot(trees,aes(Height,Volume,colour=set)) + geom_point(aes(size=Girth))
      
      
      # Instead of just circles scaled by Girth, let's also change the symbol
      ggplot(trees,aes(Height,Volume,colour=set)) + geom_point(aes(size=Girth,pch=set))
      
      # Now let's choose a specific symbol for each set. Full list of symbols at ?pch
      trees$symbol[trees$Volume<=22.7]=1
      trees$symbol[trees$Volume>22.7 & trees$Volume<=45.4]=2
      trees$symbol[trees$Volume>45.4]=3
      
      ggplot(trees,aes(Height,Volume,colour=set)) + geom_point(aes(size=Girth,pch=symbol))
      

      【讨论】:

        【解决方案6】:

        最适合我的是quote()eval() 一起使用。

        例如,让我们使用for loop 打印每一列:

        Columns <- names(dat)
        for (i in 1:ncol(dat)){
          dat[, eval(quote(Columns[i]))] %>% print
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-04-26
          • 2019-04-24
          • 2021-02-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多