【问题标题】:Using "for" loops in R package and error message "Error in `[.data.frame`(, c("date", i)) : undefined columns selected"在 R 包中使用“for”循环和错误消息“`[.data.frame`(, c("date", i)) 中的错误:选择了未定义的列”
【发布时间】:2022-01-09 03:08:48
【问题描述】:

问题与在 R 包中使用“for”循环和处理错误消息“未定义列”有关。

示例日期框架由 4 行和 10 列组成。库使用 magritter 和 dplyr。

library(magrittr)
library(dplyr)

date <- c ("2020-12-31", "2021-01-29", "2021-02-26", "2021-03-31")
v_1 <- c(66.39, 70.46, 69.37, 67.73) 
v_2 <- c(14.16, 12.31, 13.07, 12.85) 
v_3 <- c(14.37, 13.02, 13.09, 14.88) 
v_4 <- c(0.94, 0.83, 0.74, 0.79) 
v_5 <- c(0.42, 0.37, 0.33, 0.29) 
v_6 <- c(1.51, 1.30, 1.14, 1.12) 
v_7 <- c(1.84, 1.37, 1.91, 1.99) 
v_8 <- c(0.16, 0.14, 0.14, 0.14)
v_9 <- c(0.21, 0.20, 0.21, 0.21) 

raw.data <- data.frame(date, v_1, v_2, v_3, v_4, v_5, v_6, v_7, v_8, v_9)

变量 v_1 到 v_9 都被分配了一个优先级,即“高”、“中”或“低”

Priority <- c("High", "Medium", "Low")

  High <- c("v_4", "v_7")
  Medium <- c("v_2", "v_3", "v_9")
  Low <- c("v_1", "v_5", "v_6", "v_8")
  

需要整齐/长格式的输出以包含 12 行和 3 列。

12 行:重复三次的日期变量。

3 列:日期、优先级和优先级总计。 (优先级总计是属于每个优先级类别的变量的逐行总和)

      date        Priority    Priority_Total
  1  2020-12-31     High           2.78
  2  2021-01-29     High           2.20
  3  2021-02-26     High           2.65
  4  2021-03-31     High           2.78
  5  2020-12-31   Medium          28.74
  6  2021-01-29   Medium          25.53
  7  2021-02-26   Medium          26.37
  8  2021-03-31   Medium          27.94
  9  2020-12-31      Low          68.48
  10 2021-01-29      Low          72.27
  11 2021-02-26      Low          70.98
  12 2021-03-31      Low          69.28

使用粘贴和复制方法成功获得所需的输出。

请注意,“tmp”是一个临时工作空间。

  pc_output <- NULL # Required output initialized
  

   # High Priority
    
    tmp <- raw.data[,c("date",High)] %>% # Selecting date and high priority variables. 
    
    mutate(Priority_Total=select(.,-1) %>% # Generating a priority total by summing across the rows.
            apply(1,sum,na.rm=TRUE)) %>% 
            mutate(Priority="High") # Generating a priority category column containing value "High"
  
    tmp <- tmp[,c("date","Priority","Priority_Total")] # Retaining the 3 required columns
    
    pc_output <- rbind(pc_output,tmp) # Merging the derived result with pc_output 
  
# The same procedure is used for medium and low priority variables
  
    # Medium Priority 
    tmp <- raw.data[,c("date",Medium)] %>% # Selecting date and medium priority variables. 
      
      mutate(Priority_Total=select(.,-1) %>% # Generating a priority total by summing across the rows.
               apply(1,sum,na.rm=TRUE)) %>% 
      mutate(Priority="Medium") # Generating a priority category column containing value "Medium"
    
    tmp <- tmp[,c("date","Priority","Priority_Total")] # Retaining the 3 required columns
    
    pc_output <- rbind(pc_output,tmp) # Merging the derived result with pc_output 
    

    # Low Priority 
    tmp <- raw.data[,c("date",Low)] %>% # Selecting date and low priority variables. 
      mutate(Priority_Total=select(.,-1) %>% # Generating a priority total by summing across the rows.
      apply(1,sum,na.rm=TRUE)) %>% 
      mutate(Priority="Low") # Generating a priority category column containing value "Low"
    
    tmp <- tmp[,c("date","Priority","Priority_Total")] # Retaining the 3 required columns
    
    pc_output <- rbind(pc_output,tmp) # Merging the derived result with pc_output
    
    rm(tmp) # Clearing the temporary work space

    print(pc_output)

运行“粘贴和复制”方法以确保正确定义所有列。

但是当使用“for”循环时,遇到了“未定义列”的问题。

    output <- NULL

    for (i in (Priority)){
      tmp <- raw.data[,c("date",i)] %>% 
      mutate(Priority_Total=select(.,-1) %>%
          apply(1,sum,na.rm=TRUE)) %>%
          mutate(Priority=i)

      tmp <- tmp[,c("date","Priority","Priority_Total")]

  output <- rbind(output,tmp)
  }

消息:“[.data.frame(raw.data, , c("date", i)) 中的错误:选择了未定义的列”

【问题讨论】:

    标签: r for-loop


    【解决方案1】:

    循环很少是此类数据转换问题的最佳解决方案,因为存在更快且可能更易于阅读的矢量化替代方案。至于您遇到的错误 - c("date", 1) 评估为长度为 2 的向量。也就是说,R 尝试评估 raw.data[, c("date", "1")],而 raw.data[, c("date", paste0("v_", i))] 可能是您打算做的。这是没有 for 循环的 dplyr 替代方案:

    raw.data %>%
      pivot_longer(starts_with("v"),
                   names_to = "Priority") %>%
      mutate(Priority = case_when(
        Priority %in% c("v_4", "v_7") ~ "High",
        Priority %in% c("v_2", "v_3", "v_9") ~ "Medium",
        Priority %in% c("v_1", "v_5", "v_6", "v_8") ~ "Low",
        TRUE ~ NA_character_
      )) %>%
      group_by(date, Priority) %>%
      summarise(Priority_Total = sum(value, na.rm = T), .groups = "drop") %>%
      arrange(factor(Priority, levels = c("High", "Medium", "Low")))
    
    # A tibble: 12 x 3
       date       Priority Priority_Total
       <chr>      <chr>             <dbl>
     1 2020-12-31 High               2.78
     2 2021-01-29 High               2.2 
     3 2021-02-26 High               2.65
     4 2021-03-31 High               2.78
     5 2020-12-31 Medium            28.7 
     6 2021-01-29 Medium            25.5 
     7 2021-02-26 Medium            26.4 
     8 2021-03-31 Medium            27.9 
     9 2020-12-31 Low               68.5 
    10 2021-01-29 Low               72.3 
    11 2021-02-26 Low               71.0 
    12 2021-03-31 Low               69.3 
    

    【讨论】:

    • 唐纳德,您的解决方案完美运行。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2021-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-21
    • 2014-04-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多