我的for循环中的错误迭代数据框

时间:2017-06-05 23:06:54

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

我正在处理一个数据框,并在列中提取了0 t0 23的小时数据。我根据小时添加了一列作为当天的类型。我已经执行下面的循环,但得到错误。有人可以帮我解决下面的语法错误以及如何纠正错误。

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"
   }
}

2 个答案:

答案 0 :(得分:2)

仍在等待你发布你的错误,但这里是一个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>矢量化函数可以实现您想要的功能cut, if, sum, mean, max, diff, stdev, ... fns都是矢量化的,所有算术和逻辑运算符都是如此。 '矢量化'意味着您可以将整个(列)矢量作为输入提供给它们,它们会生成一个完整的(列)矢量作为输出,您可以直接将其分配给新列。非常简单,非常快,非常强大。一般来说,裤子脱掉了。请阅读R-intro.html, esp. Section 2 about vector assignment

如果你找不到或写一个向量化的fn,那么*apply函数族apply, sapply, lapply, ...也可以将你想要的任意函数应用于list / vector / dataframe / df列。

关于cut()的注释

  1. cut(data, breaks, labels, ...)是一个函数,其中data是您的输入向量(例如,您选择的列data$Requesthours),breaks是整数或数字的向量,{{1是一个命名输出的向量。标签的长度不仅仅是中断,因为5个中断将您的数据划分为6个范围。
  2. 我们希望输出向量是字符串,而不是分类,因此我们将labels应用于as.character()的输出
  3. 由于你的第一个if-else比较是cut(),我们必须将最低cutoff_hour 0调到-1,否则hr == 0会错误地给出NA。 (有一个参数(hr>=0 & hr<3),但它不是你想要的,因为它也会导致hr == 3为'Midnight',hr == 6为'Early Morning'等。)

答案 1 :(得分:0)

if(data$Requesthours>=0 & data$Requesthours<3)(以及其他类似的ifs)毫无意义,因为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提出的内容