【问题标题】:Looping monthly indices for a particular year循环特定年份的月度指数
【发布时间】:2019-02-28 08:11:05
【问题描述】:

我有一个如下图所示的数据格式,其中我们有不同 SKU 多年的销售数据,每月分发一次。

我使用该函数计算了每年的月度指数;

calc_monthly_all<- function(X){
  X$sku <- as.character(X$sku)
  X$Yearly_Avg <- rowMeans(X[,-c(1:2)])
  level_one <- X %>% dplyr::mutate_at(vars(starts_with('Month_')), funs(./Yearly_Avg))
  return(level_one)
  }

显示的数据在R中读取为'df_data',&应用函数后,输出如下,

> calc_monthly_all(df_data)
             sku Year  Month_Jan  Month_Feb Month_March Month_April Month_May Month_June Month_July Month_Aug Month_Sept
1 10929000284004 2015 0.32601608 0.19821778   0.6755053   2.0838948 0.5398826  1.7657031  1.2414692 1.1136709  0.6650728
2 10929000284004 2016 0.92209048 2.52811562   1.4961071   1.8380744 0.6534019  0.7511068  0.5190576 0.2992214  0.1038115
3 10929001124004 2014 0.04678503 0.04318618   0.4847649   0.9385797 0.9781670  0.9353407  0.7924664 1.2894674  1.2070537
4 10929001124004 2015 1.40699537 1.86480849   0.7979080   0.7520179 0.3975936  1.1719218  0.4233502 0.6419178  1.5749569
5 10929001124004 2016 0.92209048 2.52811562   1.4961071   1.8380744 0.6534019  0.7511068  0.5190576 0.2992214  0.1038115
6 10929001124104 2016 1.00160192 0.65078094   0.8191163   0.8358030 1.0112802  0.9419971  0.7209318 1.0449873  1.0337071
7 10929001124104 2017 0.83334681 0.74955923   0.7739514   1.2059589 1.1626741  1.4993773  1.0948676 0.9872054  1.1436520
  Month_Oct Month_Nov Month_Dec Yearly_Avg
1 1.5831341 1.1945229 0.6129102   3834.167
2 1.2029922 0.5434838 1.1425373   1637.583
3 2.2273273 1.7357246 1.3211372  27786.667
4 0.9569818 0.6437317 1.3678164  55131.667
5 1.2029922 0.5434838 1.1425373   1637.583
6 1.3110399 1.3426111 1.2861434 149820.000
7 0.9806706 0.8718438 0.6968927 154557.500

现在,对于每个 SKU 的每一年,我们都会获得月度指数。现在我们需要获取特定年份的指数,比如说第一年。这意味着对于每个 SKU,我们将获取它们各自第一年的月度指数,返回仅包含每个 SKU 的第一年月度指数的数据框。为此我尝试过;

calc_monthly_fys<- function(X){
  X$sku <- as.character(X$sku)
  X$Yearly_Avg <- rowMeans(X[,-c(1:2)])
  level_one <- X %>% dplyr::mutate_at(vars(starts_with('Month_')), funs(./Yearly_Avg))
  first_yr_store <- data.frame()
  for (i in unique(level_one$sku)){
    fys1 <- subset(level_one,sku %in% i)
    fys <- fys1[1,]
    df <-data.frame(fys)
    df_total <- rbind(first_yr_store,df)
    return(df_total)
  }
} 

但是,它没有给出正确的结果,只出现了第一个 SKU。

calc_monthly_fys(df_data)
             sku Year Month_Jan Month_Feb Month_March Month_April Month_May Month_June Month_July Month_Aug Month_Sept
1 10929000284004 2015 0.3260161 0.1982178   0.6755053    2.083895 0.5398826   1.765703   1.241469  1.113671  0.6650728
  Month_Oct Month_Nov Month_Dec Yearly_Avg
1  1.583134  1.194523 0.6129102   3834.167

所有 SKU 都需要这个。

这里的示例有 3 个唯一 SKU,但数据可能有“n”个 SKU。最后我需要的输出应该是下面的格式;

列的名称(SKU_1 到 SKU_N)应该是动态的(如果我们有四个唯一的 SKU,这四个 SKU 名称应该显示为列名称)。 _FYI 在这里表示'First Year Index',我想我们可以使用paste 函数在最终输出表中每个唯一SKU 名称后附加后缀_FYI

请帮助我以讨论的格式为 N 个 SKU 和 M 个年数生成月度索引。

TIA

【问题讨论】:

  • `它没有给出正确的结果,只出现了第一个 SKU。` - 我认为这主要是因为你的循环中有一个 return()

标签: r for-loop


【解决方案1】:

目前还不清楚您希望如何处理每个 SKU 的不同年份,但这可能会有所帮助。

它假定df 包含您作为calc_monthly_all(df_data) 调用的结果所显示的内容。

# Get rid of the yearly average, as it's not needed in the results
df$Yearly_Avg <- NULL

# We're going to transpose the dataframe  (turn the rows into columns,
# and the columns into rows), so make the row names what will be the 
# column names
rownames(df) <- paste0(df$sku, '_', df$Year)

# Get rid of the unnecessary sku and year columns, as they're not needed
# if we leave them, the transpose will coerce all the columns to characters
df$sku <- NULL
df$Year <- NULL

# Transpose the dataframe
df2 <- t(df)

# Get rid of "Month_" at the start of the rownames
rownames(df2) <- gsub('^Month_', '', rownames(df2))

# View the results
df2

编辑

根据您的评论和您之前的代码,函数应该是这样的:

library(dplyr)

calc_monthly_all<- function(X){
  X$sku <- as.character(X$sku)
  X$Yearly_Avg <- rowMeans(X[,-c(1:2)])
  level_one <- X %>% dplyr::mutate_at(vars(starts_with('Month_')), funs(./Yearly_Avg))

  level_one$Yearly_Avg <- NULL

  rownames(level_one) <- paste0(level_one$sku, '_', level_one$Year)
  level_one$sku <- NULL
  level_one$Year <- NULL

  result <- t(level_one)
  rownames(result) <- gsub('^Month_', '', rownames(result))
  result
}

编辑 2 如果您只想要一年的数据,您可以在转置之前过滤函数:

library(dplyr)

calc_monthly_one_year<- function(X, required_year){
  X <- X %>% filter(Year == required_year)

  X$sku <- as.character(X$sku)
  X$Yearly_Avg <- rowMeans(X[,-c(1:2)])
  level_one <- X %>% dplyr::mutate_at(vars(starts_with('Month_')), funs(./Yearly_Avg))

  level_one$Yearly_Avg <- NULL

  rownames(level_one) <- level_one$sku
  level_one$sku <- NULL
  level_one$Year <- NULL

  result <- t(level_one)
  rownames(result) <- gsub('^Month_', '', rownames(result))
  result
}

calc_monthly_one_year(df_data, 2016)

【讨论】:

  • 对不起,我无法正确理解。如果没有“return”语句,函数输出将变为“NULL”。您提供的答案应该在 for 循环内。但是,您在哪里获取每个 SKU 的第一年指数?我需要在一个函数内部使用整个过程,所以在输入数据时,我只会根据最后附加的格式得到最终输出
  • 不,我提供的答案与 for 循环是分开的。它使用问题顶部显示的calc_monthly_all 的结果。它根本不使用calc_monthly_fys(或for循环)
  • 真的很好解释。我只考虑循环,但可以用像你这样的更简单的方法来完成。非常感谢@Hobo
  • 不用担心;乐于助人
猜你喜欢
  • 2012-02-14
  • 2016-10-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-14
  • 1970-01-01
  • 2020-07-20
相关资源
最近更新 更多