将自定义功能应用于DFS列表,将另一个列表作为输入-R

发布于 2025-01-22 14:08:10 字数 1347 浏览 0 评论 0原文

我有DFS清单和年度预算清单。 每个DF代表一个营业年,每个预算代表当年的总支出。

# the business year starts from Feb and ends in Jan.
# the budget column is first populated with the % of annual budget allocation

df <- data.frame(monthly_budget=c(0.06, 0.13, 0.07, 0.06, 0.1, 0.06, 0.06, 0.09, 0.06, 0.06, 0.1, 0.15),
          month=month.abb[c(2:12, 1)])

# dfs for 3 years
df2019_20 <- df
df2020_21 <- df
df2021_22 <- df

# budgets for 3 years
budget2019_20 <- 6000000
budget2020_21 <- 7000000
budget2021_22 <- 8000000

# into lists
df_list <- list(df2019_20, df2020_21, df2021_22)
budget_list <- list(budget2019_20, budget2020_21, budget2021_22)

我已经写下了以下功能,以将正确的年份应用于Jan,并通过将相应的DFS名称删除来填写其余功能。 如果我提供单个DF和单个预算,它可以很好地工作。

budget_func <- function(df, budget){ 
  
  df_name <- deparse(substitute(df))
  
  df <- df %>%
    mutate(year=ifelse(month=="Jan",
                       as.numeric(str_sub(df_name, -2)) + 2000,
                       as.numeric(str_extract(df_name, "\\d{4}(?=_)")))
    )
  
  for (i in 1:12){ 
    
    df[i,1] <- df[i,1] * budget
    
    i <- i+1
  }
  return(df)
}

为了加快事物的速度,我想将两个列表作为参数将其作为mapply 。但是我没有得到想要的结果 - 我在做什么错?

final_budgets <- mapply(budget_func, df_list, budget_list)

I have a list of dfs and a list of annual budgets.
Each df represents one business year, and each budget represents a total spend for that year.

# the business year starts from Feb and ends in Jan.
# the budget column is first populated with the % of annual budget allocation

df <- data.frame(monthly_budget=c(0.06, 0.13, 0.07, 0.06, 0.1, 0.06, 0.06, 0.09, 0.06, 0.06, 0.1, 0.15),
          month=month.abb[c(2:12, 1)])

# dfs for 3 years
df2019_20 <- df
df2020_21 <- df
df2021_22 <- df

# budgets for 3 years
budget2019_20 <- 6000000
budget2020_21 <- 7000000
budget2021_22 <- 8000000

# into lists
df_list <- list(df2019_20, df2020_21, df2021_22)
budget_list <- list(budget2019_20, budget2020_21, budget2021_22)

I've written the following function to both apply the right year to Jan and fill in the rest by deparsing the respective dfs name.
It works perfectly if I supply a single df and a single budget.

budget_func <- function(df, budget){ 
  
  df_name <- deparse(substitute(df))
  
  df <- df %>%
    mutate(year=ifelse(month=="Jan",
                       as.numeric(str_sub(df_name, -2)) + 2000,
                       as.numeric(str_extract(df_name, "\\d{4}(?=_)")))
    )
  
  for (i in 1:12){ 
    
    df[i,1] <- df[i,1] * budget
    
    i <- i+1
  }
  return(df)
}

To speed things up I want to pass both lists as arguments to mapply. However I don't get the results I want - what am I doing wrong?

final_budgets <- mapply(budget_func, df_list, budget_list)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

那些过往 2025-01-29 14:08:10

而不是使用depars/替代(当我们传递单个数据集时它有效,并且在循环中是不同的,因为对象传递的对象不是对象名称),我们可以添加一个新参数以传递名称。此外,当我们创建list时,它也应该具有名称。我们可以使用list(DF2019_20 = DF2019_20,...)或使用setNames,或者更轻松的选项是dplyr :: lst确实返回用对象的名称传递

budget_func <- function(df, budget, nm1){ 
           df_name <- nm1
  
             df <- df %>%
               mutate(year=ifelse(month=="Jan",
                                  as.numeric(str_sub(df_name, -2)) + 2000,
                                  as.numeric(str_extract(df_name, "\\d{4}(?=_)")))
               )
  
             for (i in 1:12){ 
    
               df[i,1] <- df[i,1] * budget
    
               i <- i+1
             }
             return(df)
           }

-TESTING

df_list <- dplyr::lst(df2019_20, df2020_21, df2021_22)
budget_list <- list(budget2019_20, budget2020_21, budget2021_22)
Map(budget_func, df_list, budget_list, names(df_list))     

-OUTPUT

$df2019_20
   monthly_budget month year
1          360000   Feb 2019
2          780000   Mar 2019
3          420000   Apr 2019
4          360000   May 2019
5          600000   Jun 2019
6          360000   Jul 2019
7          360000   Aug 2019
8          540000   Sep 2019
9          360000   Oct 2019
10         360000   Nov 2019
11         600000   Dec 2019
12         900000   Jan 2020

$df2020_21
   monthly_budget month year
1          420000   Feb 2020
2          910000   Mar 2020
3          490000   Apr 2020
4          420000   May 2020
5          700000   Jun 2020
6          420000   Jul 2020
7          420000   Aug 2020
8          630000   Sep 2020
9          420000   Oct 2020
10         420000   Nov 2020
11         700000   Dec 2020
12        1050000   Jan 2021

$df2021_22
   monthly_budget month year
1          480000   Feb 2021
2         1040000   Mar 2021
3          560000   Apr 2021
4          480000   May 2021
5          800000   Jun 2021
6          480000   Jul 2021
7          480000   Aug 2021
8          720000   Sep 2021
9          480000   Oct 2021
10         480000   Nov 2021
11         800000   Dec 2021
12        1200000   Jan 2022

Instead of using deparse/substitute (which works when we are passing a single dataset, and is different in the loop because the object passed is not the object name), we may add a new argument to pass the names. In addition, when we create the list, it should have the names as well. We can either use list(df2019_20 = df2019_20, ...) or use setNames or an easier option is dplyr::lst which does return with the name of the object passed

budget_func <- function(df, budget, nm1){ 
           df_name <- nm1
  
             df <- df %>%
               mutate(year=ifelse(month=="Jan",
                                  as.numeric(str_sub(df_name, -2)) + 2000,
                                  as.numeric(str_extract(df_name, "\\d{4}(?=_)")))
               )
  
             for (i in 1:12){ 
    
               df[i,1] <- df[i,1] * budget
    
               i <- i+1
             }
             return(df)
           }

-testing

df_list <- dplyr::lst(df2019_20, df2020_21, df2021_22)
budget_list <- list(budget2019_20, budget2020_21, budget2021_22)
Map(budget_func, df_list, budget_list, names(df_list))     

-output

$df2019_20
   monthly_budget month year
1          360000   Feb 2019
2          780000   Mar 2019
3          420000   Apr 2019
4          360000   May 2019
5          600000   Jun 2019
6          360000   Jul 2019
7          360000   Aug 2019
8          540000   Sep 2019
9          360000   Oct 2019
10         360000   Nov 2019
11         600000   Dec 2019
12         900000   Jan 2020

$df2020_21
   monthly_budget month year
1          420000   Feb 2020
2          910000   Mar 2020
3          490000   Apr 2020
4          420000   May 2020
5          700000   Jun 2020
6          420000   Jul 2020
7          420000   Aug 2020
8          630000   Sep 2020
9          420000   Oct 2020
10         420000   Nov 2020
11         700000   Dec 2020
12        1050000   Jan 2021

$df2021_22
   monthly_budget month year
1          480000   Feb 2021
2         1040000   Mar 2021
3          560000   Apr 2021
4          480000   May 2021
5          800000   Jun 2021
6          480000   Jul 2021
7          480000   Aug 2021
8          720000   Sep 2021
9          480000   Oct 2021
10         480000   Nov 2021
11         800000   Dec 2021
12        1200000   Jan 2022
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文