【问题标题】:Unable to access a specific variable inside a for loop无法访问 for 循环内的特定变量
【发布时间】:2019-11-08 02:03:57
【问题描述】:

考虑一下这个“for循环”

alpha <- data.frame()

for(i in 1:30)
{
 nam <- paste("d", i, sep = "")
 assign(nam,  filter(a1,day(date)==i))
 nam <- aggregate(steps~group,nam,sum()) #I want to access d[i] through variable "nam" which is showing error
alpha <- rbind(alpha,nam) 
}

在for循环的每次迭代中,我想过滤'days'(从1到30不等),并使用聚合函数根据列组进行分组,最后rbind每次迭代创建一个新的数据框alpha

但这会在 for 循环内的第 3 行引发此错误

Error in eval(predvars, data, env) : 
  invalid 'envir' argument of type 'character'

我的数据框“a1”

 tibble: 8,640 x 5
   steps date       interval interval.1          group
   <dbl> <fct>         <int> <dttm>              <fct>
 1     0 2012-11-01        0 2012-11-01 00:00:00 0    
 2     0 2012-11-01        5 2012-11-01 00:05:00 0    
 3     0 2012-11-01       10 2012-11-01 00:10:00 0    
 4     0 2012-11-01       15 2012-11-01 00:15:00 0    
 5     0 2012-11-01       20 2012-11-01 00:20:00 0    
 6     0 2012-11-01       25 2012-11-01 00:25:00 0    
 7     0 2012-11-01       30 2012-11-01 00:30:00 0    
 8     0 2012-11-01       35 2012-11-01 00:35:00 0    
 9     0 2012-11-01       40 2012-11-01 00:40:00 0    
10     0 2012-11-01       45 2012-11-01 00:45:00 0    
# ... with 8,630 more rows

请解释一下解决这个问题的方法?达到我想要的输出的任何答案就足够了

编辑 -1

输入(头(a1,10))=


structure(list(steps = c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0), date = structure(c(32L, 
32L, 32L, 32L, 32L, 32L, 32L, 32L, 32L, 32L), .Label = c("2012-10-01", 
"2012-10-02", "2012-10-03", "2012-10-04", "2012-10-05", "2012-10-06", 
"2012-10-07", "2012-10-08", "2012-10-09", "2012-10-10", "2012-10-11", 
"2012-10-12", "2012-10-13", "2012-10-14", "2012-10-15", "2012-10-16", 
"2012-10-17", "2012-10-18", "2012-10-19", "2012-10-20", "2012-10-21", 
"2012-10-22", "2012-10-23", "2012-10-24", "2012-10-25", "2012-10-26", 
"2012-10-27", "2012-10-28", "2012-10-29", "2012-10-30", "2012-10-31", 
"2012-11-01", "2012-11-02", "2012-11-03", "2012-11-04", "2012-11-05", 
"2012-11-06", "2012-11-07", "2012-11-08", "2012-11-09", "2012-11-10", 
"2012-11-11", "2012-11-12", "2012-11-13", "2012-11-14", "2012-11-15", 
"2012-11-16", "2012-11-17", "2012-11-18", "2012-11-19", "2012-11-20", 
"2012-11-21", "2012-11-22", "2012-11-23", "2012-11-24", "2012-11-25", 
"2012-11-26", "2012-11-27", "2012-11-28", "2012-11-29", "2012-11-30"
), class = "factor"), interval = c(0L, 5L, 10L, 15L, 20L, 25L, 
30L, 35L, 40L, 45L), interval.1 = structure(c(1351708200, 1351708500, 
1351708800, 1351709100, 1351709400, 1351709700, 1351710000, 1351710300, 
1351710600, 1351710900), class = c("POSIXct", "POSIXt"), tzone = ""), 
    group = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L
    ), .Label = c("0", "100", "200", "300", "400", "500", "600", 
    "700", "800", "900", "1000", "1100", "1200", "1300", "1400", 
    "1500", "1600", "1700", "1800", "1900", "2000", "2100", "2200", 
    "2300"), class = "factor")), row.names = c(NA, -10L), class = c("tbl_df", 
"tbl", "data.frame"))

【问题讨论】:

  • 请先阅读?assign。无论如何,您想要的输出到底是什么?您有什么理由要使用显式循环吗?
  • 忘记assign 的存在。学习改用列表。
  • 这是我期望做的@NelsonGon:在for循环的每次迭代中,我想过滤“天”(从1到30),并使用聚合函数根据列组和最后 rbind 每次迭代创建一个新的数据框 alpha
  • 您能否将dput(head(df,10)) 的输出添加到您的问题中?
  • aggregate(steps ~ group + day(date), data=a1, FUN=sum)

标签: r dataframe for-loop aggregate assign


【解决方案1】:

尝试根据date 拆分数据,然后为每个组拆分aggregate

lst1 <- lapply(split(a1, a1$date), function(x) aggregate(steps~group,x,sum))

这应该为您提供每个日期的数据框列表,其中包含 sumstepsgroup 。您可以通过lst1[[1]]lst1[[2]] 访问单个数据框。


要在一个数据帧中获得输出,我们可以使用do.call

do.call(rbind, lapply(split(a1, a1$date), function(x) aggregate(steps~group,x,sum)))

【讨论】:

  • 这行得通....但整体上很难进一步工作。我希望将所有列表强制转换为单个数据框。我尝试使用相同的方法: df1
  • @AnanyaVidyanathan 我们可以使用do.call。更新了答案。
  • @AnanyaVidyanathan 哦..如果您希望在单个数据框中再次使用所有内容。那不就是aggregate(steps~group + date, x, sum)吗?
  • 但我希望在我的最终数据框中也包含 interval.1 列,但在聚合函数中,我们只会得到“steps”和“groups”列。我也尝试过使用 aggregate(steps ~ cbind(group + day(interval.1),interval.1), data=a1, FUN=sum) @Ronak 你明白我的要求吗?
  • @AnanyaVidyanathan 每个组都有不同的interval.1 值,您想选择哪一个?也许如果你想保持最大值a1 %&gt;% group_by(group, date) %&gt;% mutate(steps = sum(steps)) %&gt;% slice(which.max(interval.1))
【解决方案2】:

由于您无论如何都在使用 dplyr,因此您可以使用 summarise 而不是 aggregate,这可以大大简化事情。给定这样的数据框(请注意,我遗漏了一些不相关的变量):

# A tibble: 30 x 3
   steps interval            group
   <int> <dttm>              <int>
 1     1 2012-11-01 00:00:00     1
 2     4 2012-11-01 00:05:00     1
 3     4 2012-11-01 00:10:00     1
 4     5 2012-11-01 00:15:00     1
 5     6 2012-11-01 00:20:00     1
 6     6 2012-11-01 00:25:00     2
 7     6 2012-11-01 00:30:00     2
 8     7 2012-11-01 00:35:00     2
 9     9 2012-11-01 00:40:00     2
10    10 2012-11-01 00:45:00     2
# … with 20 more rows

执行以下操作,按dategroup 分组,然后为每个计算摘要(在本例中为steps 的总和):

df %>% 
    group_by(date = date(interval), group) %>% 
    summarize(sum = sum(steps))

这会产生这样的结果:

# A tibble: 6 x 3
# Groups:   date [3]
  date       group   sum
  <date>     <int> <int>
1 2012-11-01     1    20
2 2012-11-01     2    38
3 2012-11-02     1    14
4 2012-11-02     2    42
5 2012-11-03     1    12
6 2012-11-03     2    38

这里的主要好处是清晰,并且您可以计算组总和,而无需事后堆叠数据帧。或者,如果您想坚持使用基本 R,也可以使用 aggregate(steps ~ group + date(interval), df, sum)aggregate(df$steps, by = list(group = df$group, date = date(df$interval)), sum) 之类的东西,在这种特殊情况下,它们也是非常简洁的选项。

数据:

df <- structure(list(steps = c(1L, 4L, 4L, 5L, 6L, 6L, 6L, 7L, 9L, 
10L, 1L, 2L, 3L, 3L, 5L, 7L, 8L, 8L, 9L, 10L, 1L, 2L, 2L, 3L, 
4L, 6L, 6L, 7L, 9L, 10L), interval = structure(c(1351728000, 
1351728300, 1351728600, 1351728900, 1351729200, 1351729500, 1351729800, 
1351730100, 1351730400, 1351730700, 1351814400, 1351814700, 1351815000, 
1351815300, 1351815600, 1351815900, 1351816200, 1351816500, 1351816800, 
1351817100, 1351900800, 1351901100, 1351901400, 1351901700, 1351902000, 
1351902300, 1351902600, 1351902900, 1351903200, 1351903500), class = c("POSIXct", 
"POSIXt"), tzone = "UTC"), group = c(1L, 1L, 1L, 1L, 1L, 2L, 
2L, 2L, 2L, 2L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 1L, 1L, 
1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L)), row.names = c(NA, -30L), class = c("tbl_df", 
"tbl", "data.frame"))

【讨论】:

  • 是的人@gersht ....我完全明白你要说什么.....但是它在我的代码中显示了这个错误Error in as.POSIXlt.numeric(x, tz = tz(x)) : 'origin' must be supplied
  • @AnanyaVidyanathan 我确定这与date(interval) 有关。如果您查看我的dput 输出,您将看到tzone = "UTC",而在您的输出中您将看到tzone = "",即没有时区。我的合成数据不太可能完美地代表您的真实数据(因此为我们提供真实数据的代表性样本很重要)。你可以给你的interval 列一个时区,或者,因为你已经有一个date 变量(作为一个因素),你可以使用它来代替 - 即只是date 而不是date(interval)date(df$interval) .
猜你喜欢
  • 2014-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-04
  • 1970-01-01
  • 1970-01-01
  • 2021-04-07
  • 1970-01-01
相关资源
最近更新 更多