R语言 如何通过变量名调用对象?

btxsgosb  于 2023-03-05  发布在  其他
关注(0)|答案(2)|浏览(261)

谢谢大家的关注!真的很感激。用一个可复制的代码,将是:

d <- data.frame(school = rep(LETTERS[1:4], times = c(25, 25, 25, 25)),
                student = rep(1:25, times=c(4)), 
                  week = seq(from = 1, to = 25, by= 5),
                  crit1fl = sample(0:1, n, replace = TRUE),
                  crit2fl = sample(0:1, n, replace = TRUE),
                  crit3fl = sample(0:1, n, replace = TRUE))

d2 <- d %>% 
  count(school, week, crit1fl) %>% 
  group_by(school, week) %>% 
  mutate(prop = n/sum(n)) %>% 
  arrange(school, week)

d2 %>% 
  ggplot(aes(x=as.factor(week), y=n, fill=crit1fl)) +
  geom_bar(position='fill', stat= 'identity') + 
  facet_wrap(~school) + 
  geom_text(
    aes(label=scales::percent(prop)),
    position='fill', vjust=1.5, color='white',
    data = d2[d2$crit1fl =='Y', ]) +
  labs(title= 'Proportion of subjects meeting the citeria', 
       y='Proportion', x = 'Week')

然后我想循环crit1到3fl(这是一个简单的例子,但是我的数据中有很多fl变量)来输出图形。
使用{{varname}}似乎可以工作,但不确定为什么只有最后一个图形(使用crit3fl的图形)输出,而不是迭代中的所有critfl变量。并且{{}}在geom_text中不工作。
在以下情况下不起作用:

critvars <- paste0("crit", 1:3, "fl")
for (varname in critvars) {
  d2 <- d %>% 
    count(school, week,  {{ varname }}) %>% 
    group_by(school, week) %>% 
    mutate(prop = n/sum(n)) %>% 
    arrange(school, week)
  
  
g <- d2 %>% 
    ggplot(aes(x=as.factor(week), y=n, fill= {{ varname }})) +
    geom_bar(position='fill', stat= 'identity') + 
    facet_wrap(~school) + 
    # geom_text(
    #   aes(label=scales::percent(prop)),
    #   position='fill', vjust=1.5, color='white',
    #   data = d2[d2$crit1fl =='Y', ]) +
    labs(title= 'Proportion of subjects meeting the citeria', 
         y='Proportion', x = 'Week')

g

}

原始问题:我有变量名:crit1fl,crit2fl,... crit10fl想要遍历变量名以进行分析。

for (i in 1:10) {

  d %>% 
    count(school, week, critifl)
  .
  .  
}

如何使用for循环索引调用变量?

rseugnpd

rseugnpd1#

一种选择是使用get,有几种方法可以做到这一点。不清楚是要使用循环索引遍历列名本身,还是将循环索引用作连续数值--我假设使用后者,因为这是当前分配索引的方式。我将使用感兴趣的列名定义一个向量nnames,然后在循环中使用get(names[i])
下面我稍微修改了一下循环,打印出前三个观察结果,看看它在做什么(因为你没有在循环中赋值d):

#create a vector of names
nnames <- names(d)[grep("crit", names(d))]

# run loop 
for(i in seq(nnames)){
  print(head(
    d %>% 
      count(school, 
            week, 
            crit = get(nnames[i])
  ), 3))
}

#   school week crit n
# 1      A    2    0 3
# 2      B    1    0 1
# 3      B    2    0 2
#   school week crit n
# 1      A    2    0 1
# 2      A    2    1 2
# 3      B    1    1 1
#   school week crit n
# 1      A    2    1 1
# 2      A    2    2 2
# 3      B    1    2 1

这种方法的优点是nnames不必遵循特定的模式(虽然这里使用grep是为了方便,但也可以是names <- c("apples", "oranges", "potatoes"))。在更罕见的情况下,除了i的值之外,所有列都具有完全相同的模式,您可以简单地使用以下代码:

for(i in 1:3){
  print(head(
    d %>% 
      count(school, 
            week, 
            crit = get(paste0("crit",i,"fl")))
    ))
}

其提供相同的输出。
我使用的数据是:

set.seed(123)
n <- 100
d <- data.frame(school = sample(LETTERS, n, replace = TRUE),
                week = sample(1:2, n, replace = TRUE),
                crit1fl = sample(0, n, replace = TRUE),
                crit2fl = sample(0:2, n, replace = TRUE),
                crit3fl = sample(0:2, n, replace = TRUE),
                ignore = sample(LETTERS, n, replace = TRUE))
osh3o9ms

osh3o9ms2#

虽然在R中通过编程构造和使用变量名是可能的(也不是特别困难),但这通常不是一个好主意,因为它会导致代码脆弱和难以维护。是的,这很重要,即使在研究脚本中也是如此。没有什么比尝试使用别人的研究代码却无法理解它更令人沮丧的了。

你的例子,Dplyr

假设你正在使用Dplyr,这个库 * 已经 * 为我们提供了一些工具,让我们可以通过编程的方式处理 Dataframe 中的变量名,而不用直接构造R代码对象(“名称”,又名“符号”),这个工具就是“包含操作符”{{和“注入操作符”!!
它在这里的用法很简单:

# Construct your desired variable names
critvars <- paste0("crit0", 1:10, "fl")

# Loop over each variable, performing operations as desired
for (varname in critvars) {
    mydata %>% count(school, week, {{ varname }}) %>% ...
}

这些操作符在Rlang文档here中有更详细的描述,在Dplyr文档中也有提及,但它们没有突出显示,术语非常迟钝和混乱(包括并特别是对经验丰富的Lisp用户!),甚至没有提到!!的使用。
我认为这大致反映了围绕“Tidyverse”生态系统的一种态度问题,这就是为什么我建议初学者不要过度依赖它,如果你想真正学会使用R。
注意,{{运算符***只在某些特殊设计的函数***中起作用。在基本R函数和大多数其他不属于Tidyverse的R函数中,{{!!将被区别对待。
有关使用这些运算符在 Dataframe 中构造 new 变量名的示例,请参见https://stackoverflow.com/a/26003971/2954547(使用mutate)。

其他用途,无Dplyr

使用 non-Dplyr函数时,这会稍微简单一些,对数据框使用标准[[选择操作符:

for (varname in critvars) {
    y <- mydata[[varname]]
    do_something(y)
}

有关更多示例和讨论,请参见here

相关问题