【问题标题】:R - recursively create dataframe columns via index inside functionR - 通过函数内部的索引递归地创建数据框列
【发布时间】:2021-08-21 21:40:16
【问题描述】:

我有一个包含大量年度数据的数据框。例如,考虑以下玩具示例:

dat <- data.frame(id = 1:2, quantity = 3:4, agg_2002 = 5:6, agg_2003 = 7:8, agg_2020 = 9:10)

我想做的是:

  1. 在列名集合names(df)中查找名为“agg_”的列

  2. names(df) 中的“agg_”替换为“change_”

  3. 计算每年的相对变化,例如,

    df$change_2002 &lt;- df$agg_2002/df$agg_2002(因为 2002 年是第一年)

    df$change_2003 &lt;- df$agg_2003/df$agg_2002

    df$change_2004 &lt;- df$agg_2004/df$agg_2003...一直到 2020 年或列名中带有“agg_”的最新值。

我目前拥有的是以下功能:

func <- function(dat, overwrite = FALSE) {
  nms <- grep("agg_[0-9]+$", names(dat), value = TRUE)
  revnms <- gsub("agg_", "chg_", nms)
  for i = 1:ncol(df) %in% revnms{
    dat[, rvnms][i] <- lapply(dat[, rvnms][i], `/`, dat[, rvnms][i-1])
  }
  dat
}

我正在苦苦挣扎的是索引。如何让 R 递归地进行上述计算而无需手动进行?所需的结果是附加到原始数据框的“chg_”列:

  id quantity agg_2002 agg_2003 agg_2020 chg_2002 chg_2003 chg_2020
1  1        3        5        7        9        1     1.40     1.28
2  2        4        6        8       10        1     1.33     1.25

如果可能,我想通过lapply 修改上面指定的函数以产生所需的结果。欢迎所有想法。谢谢。

更新:我更喜欢使用 lapply 或可以容纳不同数据类型的东西

【问题讨论】:

    标签: r dataframe recursion lapply


    【解决方案1】:

    您可以将表格制作成长格式,更改名称(可以使用gsub),然后传播回来

    library(tidyverse)
    library(stringr)
    
    df <- dat %>% pivot_longer(-c(id,quantity), names_to = "agg", values_to = "year") %>% 
      mutate(agg = str_replace(agg, "agg", "change")) %>% 
      group_by(id) %>% 
      mutate(year = ifelse(is.na(lag(year)), year/year, year/lag(year))) %>% # Divide itself if there is no lag(year)
      pivot_wider(names_from = "agg", values_from = "year") 
    
    inner_join(dat, df, by = c("id","quantity"))
    
      id quantity agg_2002 agg_2003 agg_2020 change_2002 change_2003 change_2020
    1  1        3        5        7        9           1    1.400000    1.285714
    2  2        4        6        8       10           1    1.333333    1.250000
    

    【讨论】:

    • 这看起来不错且可读。问题:如果我向dat 添加另一个“agg_”列,这会起作用吗?我希望能够添加“agg_”列并对其进行更新。此外,change_2002 在此解决方案中是 NA 而不是 1
    • 只要名称是agg_,它应该可以正常工作。对于 NA 列,这是由于没有先前的参数可以划分。只需将该列更改为 1。
    • 我已经使用ifelse 编辑了您的条件的代码。看看吧。
    • 这适用于玩具示例,因为所有列都是相同的。当我在包含 向量的实际数据框上运行时,我收到无法组合它们的错误。
    • 我修改了它,效果很好。非常感谢您的帮助。
    【解决方案2】:

    这是dplyrtidyr 的解决方案:

    library(tidyr)
    library(dplyr)
    
    dat %>%
      pivot_longer(cols = starts_with("agg"),
                          names_to = "year",
                          names_prefix = "agg_",
                          values_to = "agg") %>%
      group_by(id) %>%
      arrange(year) %>%
      mutate(change = agg / lag(agg, 1)) %>%
      pivot_wider(names_from = year, values_from = c("agg", "change"))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-15
      • 1970-01-01
      • 1970-01-01
      • 2022-01-26
      • 2019-04-08
      • 2021-07-19
      相关资源
      最近更新 更多