【问题标题】:Bug in my for-loop to iterate over data frame我的 for 循环中的错误以迭代数据框
【发布时间】:2017-06-05 23:06:54
【问题描述】:

我正在处理一个数据框,并提取了从 0 到 23 小时数据的列。我正在添加一列作为基于小时的日期类型。我在下面执行了 for 循环,但出现错误。有人可以帮助我以下语法有什么问题以及如何更正。

for(i in data$Requesthours) {
   if(data$Requesthours>=0 & data$Requesthours<3) {
     data$Partoftheday <- "Midnight"
   } else if(data$Requesthours>=3 & data$Requesthours<6) {
     data$Partoftheday <- "Early Morning"
   } else if(data$Requesthours>=6 & data$Requesthours<12) {
     data$Partoftheday <- "Morning"
   } else if(data$Requesthours>=12 & data$Requesthours<16) {
     data$Partoftheday <- "Afternoon"
   } else if(data$Requesthours>=16 & data$Requesthours<20) {
     data$Partoftheday <- "Evening"
   } else if(data$Requesthours>=20 & data$Requesthours<=23) {
     data$Partoftheday <- "Night"
   }
}

【问题讨论】:

  • a) “不断出错”告诉我们什么;请发布错误的文本。包括它引用的代码行,以便我们可以看到它是由 for 语句还是 if 语句引起的? b) 另外我们没有您的数据,请添加一个最小可重现示例 How to make a great R reproducible example?。 c) 还请格式化和缩进您的代码,使其清晰易读;这次是我为你做的。
  • 另外,请参阅我对编码技巧的回答,该技巧会将其简化为单行(并绕过您的错误)
  • 还在等你发布你的错误。我怀疑您的 data$Requesthours 列中有 NA。但实际上不是......
  • 您的错误是 for(i in data$Requesthours) 正在尝试迭代您的数据框,但会将行索引与数据值混淆。

标签: r for-loop if-statement vectorization cut


【解决方案1】:

仍在等待您发布您的错误,但这里有一个 R 编码技巧,可以将其简化为单行(并绕过您的错误)。而且它会更快(它是矢量化的,不像你的 for-loop 和 if-else-ladder)。

data$Partoftheday <- as.character(
  cut(data$Requesthours,
      breaks=c(-1,3,6,12,16,20,24),
      labels=c('Midnight', 'Early Morning', 'Morning', 'Afternoon', 'Evening', 'Night')
  )
)
# see Notes on cut() at bottom to explain this

现在回到您的错误:您对如何遍历 R 中的列感到困惑。for(i in data$Requesthours) 正在尝试遍历您的 df,但您将索引与数据值混淆了。此外,您尝试使 i 成为迭代器,但是您没有在循环内的任何地方引用值 i,而是引用了 data$Requesthours,这是一整列而不是单个值(如何循环内容知道你指的是哪个值?他们不知道。你可以使用像for (i in 1:nrow(data) ...for (i in seq_along(data) ...这样丑陋的显式索引循环,然后访问data[i,]$Requesthours,但请不要。因为...

关于学习 R 的一大习惯用法通常是,当您编写一个 for 循环来迭代数据帧或 df 列时,如果没有

,您应该停止思考(或研究) R 中的 em>vectorized 函数可以满足您的需求

cut, if, sum, mean, max, diff, stdev, ... fns 都是矢量化的,所有算术和逻辑运算符也是如此。 “向量化”意味着您可以将整个(列)向量作为输入提供给它们,并且它们会生成整个(列)向量作为输出,您可以将其直接分配给新列。非常简单,非常快速,非常强大。通常会在for-loops上击败裤子。请阅读R-intro.html, esp. Section 2 about vector assignment

如果您找不到或无法编写矢量化 fn,还有 *apply 系列函数 apply, sapply, lapply, ... 可将您想要的任意函数应用于列表/向量/数据帧/df 列。

关于 cut() 的说明

  1. cut(data, breaks, labels, ...) 是一个函数,其中data 是您的输入向量(例如,您选择的列data$Requesthours),breaks 是整数或数字向量,labels 是用于命名输出的向量。标签的长度比中断多一,因为 5 个中断将您的数据分成 6 个范围。
  2. 我们希望输出向量是字符串,而不是分类,因此我们将as.character() 应用于cut() 的输出
  3. 由于您的第一个 if-else 比较是 (hr&gt;=0 &amp; hr&lt;3),我们必须将最低的 cutoff_hour 0 调整为 -1,否则 hr==0 会错误地给出 NA。 (有一个参数include.lowest=TRUE/FALSE,但这不是您想要的,因为它还会导致 hr==3 为“午夜”,hr==6 为“清晨”等)

【讨论】:

    【解决方案2】:

    if(data$Requesthours&gt;=0 &amp; data$Requesthours&lt;3)(和其他类似的 if)没有意义,因为data$Requesthours 是一个向量。您应该尝试以下任一方法:


    解决方案 1:

    for(i in seq(length(data$Requesthours))) {
        if(data$Requesthours[i]>=0 & data$Requesthours[i]<3)
            data$Partoftheday[i] <- "Midnight"
        ....
    }
    

    这个解决方案非常缓慢而且非常丑陋,但它会起作用。


    解决方案 2:

    data$Partoftheday[data$Requesthours>=0 & data$Requesthours<3] <- "Midnight"
    ...
    

    解决方案 3 = smci 提出的建议

    【讨论】:

      猜你喜欢
      • 2013-07-02
      • 2023-03-30
      • 1970-01-01
      • 2013-12-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多