使用for循环中的dplyr select和mutate函数向数据框添加新变量

时间:2018-05-11 21:31:06

标签: r for-loop dplyr

如果这是重复的,请告诉我。我已经查看了Stack并找到了类似的问题,但我没有完全回答我的问题。我是初学者,所以我感谢任何人的帮助。

我正在尝试将年度汇总变量添加到月度数据的数据框中(即,跨行汇总)。以下是每月数据有限的示例数据框架。

df <- data.frame("Jan.2012" = c(1, 4, 5, 6), "Feb.2012" = c(3, 5, 7, 9),
 "Jan.2013" = c(6, 8, 9, 10), "Feb.2013" = c(7, 5, 11, 13), "Jan.2014" = c(6, 8, 9, 11), 
 "Feb.2014" = c(7, 3, 5, 9))

新变量将命名为TotalYr2012,TotalYr2013等。例如,TotalYr2012 = c(4,9,12,15)等。

我正在尝试迭代for循环(不是我所知道的最佳实践)来生成这些变量。我知道我在使用assign语句时遇到了一些错误,并且我收到了错误。

for (i in 2012:2014) {
  varname <- paste("TotalYr", i, sep = "")
    assign(df$varname, df %>% select(contains("i")) %>% 
     mutate(varname = sum()))
}

感谢您的帮助!

2 个答案:

答案 0 :(得分:2)

您可以使用current_user.waterusage.household_sizefor-loop函数来计算每年的摘要,以避免tidyr::gather

zoo::yearmon

答案 1 :(得分:2)

你遇到了很多问题。

  1. $不适用于变量。请改用[[[See this R-FAQ for additional info。你的缩进也是混乱的,让它保持一致:

    for (i in 2012:2014) {
      varname <- paste("TotalYr", i, sep = "")
      assign(df[[varname]], df %>% select(contains("i")) %>% 
        mutate(varname = sum()))
    }
    
  2. assign不是必需的,只需使用<-(或=)即可。你几乎不应该使用assign()

    for (i in 2012:2014) {
      varname <- paste("TotalYr", i, sep = "")
      df[[varname]] <- df %>% select(contains("i")) %>% 
        mutate(varname = sum()))
    }
    
  3. "i"是一个字符串,它的值始终是字母"i",就像2的值总是2一样。即使在contains()您希望使用,您也已分配给对象i (尽管该值需要是一个字符串,也就是说,它必须是类character):

    for (i in 2012:2014) {
      varname <- paste("TotalYr", i, sep = "")
      df[[varname]] <- df %>% select(contains(as.character(i))) %>% 
        mutate(varname = sum()))
    }
    
  4. mutateselect会返回数据框,这意味着您的代码正在尝试分配单列数据框df[[varname]]。我们只想分配一个列向量,而不是整个数据帧。因此,我们使用dplyr::pull

    提取列向量
    for (i in 2012:2014) {
      varname <- paste("TotalYr", i, sep = "")
      df[[varname]] <- df %>% select(contains(as.character(i))) %>% 
        mutate(varname = sum())) %>%
        pull()
    }
    
  5. 在您的控制台中输入sum() - 您获得0。你需要给sum()一些东西。让我们完全摆脱mutate sum pull for (i in 2012:2014) { varname <- paste("TotalYr", i, sep = "") df[[varname]] <- df %>% select(contains(as.character(i))) %>% pull %>% sum } ed向量,这样我们就不用担心它的名字了:

    result
  6. 好的,它现在有用了。但是,您要将这些新值添加到旧数据框中,该数据框有一堆行。新值只是单个值,因此它们会在数据帧的每一行上重复&#34;再循环&#34;重复。让我们创建一个新的result = list() for (i in 2012:2014) { varname <- paste("TotalYr", i, sep = "") result[[varname]] <- df %>% select(contains(as.character(i))) %>% pull %>% sum } result = as.data.frame(result) result # TotalYr2012 TotalYr2013 TotalYr2014 # 1 24 36 24 数据框,而我们的结果只有一行:

    for
  7. 现在它有效,并提供了一个有效的解决方案。但是,它仍然是凌乱的。 # See MKR's answer. It's the way you should actually do this. 循环通常是不必要的。我们有更好的工具来整理数据。

    @media screen and (min-width: 768px) {
      .video {
        width: 65%;
        float:left;
      }
      .sidebar, .related-video {
        width: 35%;
        float: left;
      }
      .comment {
        width: 100%;
        float: left;
      }
    }
    
    /* Hide the related video in screens exceeding 768px */
    @media screen and (max-width: 768px) {
       .related-video {
         display: none;
       }
    }