【问题标题】:Computing Growth Rates计算增长率
【发布时间】:2020-05-20 21:00:12
【问题描述】:

我正在研究一个福利工资补贴计划的数据集,其中每个工人的工资结构如下:

df <- structure(list(wage_1990 = c(13451.67, 45000, 10301.67, NA, NA, 
8726.67, 11952.5, NA, NA, 7140, NA, NA, 10301.67, 7303.33, NA, 
NA, 9881.67, 5483.33, 12868.33, 9321.67), wage_1991 = c(13451.67, 
45000, 10301.67, NA, NA, 8750, 11952.5, NA, NA, 7140, NA, NA, 
10301.67, 7303.33, NA, NA, 9881.67, 5483.33, 12868.33, 9321.67
), wage_1992 = c(13451.67, 49500, 10301.67, NA, NA, 8750, 11952.5, 
NA, NA, 7140, NA, NA, 10301.67, 7303.33, NA, NA, 9881.67, NA, 
12868.33, 9321.67), wage_1993 = c(NA, NA, 10301.67, NA, NA, 8750, 
11958.33, NA, NA, 7140, NA, NA, 10301.67, 7303.33, NA, NA, 9881.67, 
NA, NA, 9321.67), wage_1994 = c(NA, NA, 10301.67, NA, NA, 8948.33, 
11958.33, NA, NA, 7140, NA, NA, 10301.67, 7303.33, NA, NA, 9881.67, 
NA, NA, 9321.67), wage_1995 = c(NA, NA, 10301.67, NA, NA, 8948.33, 
11958.33, NA, NA, 7140, NA, NA, 10301.67, 7303.33, NA, NA, 9881.67, 
NA, NA, 9321.67), wage_1996 = c(NA, NA, 10301.67, NA, NA, 8948.33, 
11958.33, NA, NA, 7291.67, NA, NA, 10301.67, 7303.33, NA, NA, 
9881.67, NA, NA, 9321.67)), class = c("tbl_df", "tbl", "data.frame"
), row.names = c(NA, -20L))

我尝试了一种建议的解决方案,它在上述代码之后运行此代码:

average_growth_rate <- apply(df, 1, function(x) {
        x1 <- x[!is.na(x)]
         mean(x1[-1]/x1[-length(x1)]-1)})
out <- data.frame(rowid = seq_len(nrow(df)), average_growth_rate)
out[!is.na(out$average_growth_rate),]

但我不断收到此错误:

dim(X)

我想做以下事情:1-创建一个变量,显示每个工人的工资年增长率或缺乏。

我面临的实际问题是,每个观察都排成一行,而第一个工人在 1990 年加入该计划,其他人可能在 1993 年或 1992 年加入。因此,有没有办法应用增长率根据每个工人工作的具体年份,而不是对所有观察结果应用通用增长公式?

我对每一行的预期输出将是一个新列

      average wage growth rate
1-         15%
2-         9%
3-         12%

运行以下代码查看我感兴趣的变量的描述性统计数据后:

skim(df$average_growth_rate)

我得到以下结果:

"Variable contains Inf or -Inf value(s) that were converted to NA.── Data Summary ────────────────────────
                           Values                      
Name                       gosi_beneficiary_growth$a...
Number of rows             3671                        
Number of columns          1                           
_______________________                                
Column type frequency:                                 
  numeric                  1                           
________________________                               
Group variables            None                        

── Variable type: numeric ──────────────────────────────────────────────────────────────────────────────
  skim_variable n_missing complete_rate  mean    sd    p0    p25   p50    p75  p100 hist 
1 data               1348         0.633   Inf   Inf    -1 -0.450     0 0.0568  
"

我不确定为什么我的平均值和标准差值是 Inf。

【问题讨论】:

  • 你的预期输出是什么
  • 好问题,我已经编辑了我的帖子。让我知道这是否有帮助。
  • 您能解释一下您是如何达到第一行的 15% 的吗?
  • 只是一个假设的例子,不是基于数据...更多关于我希望最终输出的样子

标签: r dataframe dplyr data.table tidyverse


【解决方案1】:

这是一种方法:

library(tidyverse)

growth <- df %>% 
  rowid_to_column() %>%
  gather(key, value, -rowid) %>% 
  drop_na() %>% 
  arrange(rowid, key) %>% 
  group_by(rowid) %>% 
  mutate(yoy = value / lag(value)-1) %>% 
  summarise(average_growth_rate = mean(yoy, na.rm=T))

# A tibble: 12 x 2
   rowid average_growth_rate
   <int>               <dbl>
 1     1           0        
 2     2           0.05     
 3     3           0        
 4     6           0.00422  
 5     7           0.0000813
 6    10           0.00354  
 7    13           0        
 8    14           0        
 9    17           0        
10    18           0        
11    19           0        
12    20           0        

为了强调所有这些 0 都是预期的,这里是数据框:

> head(df)
# A tibble: 6 x 7
  wage_1990 wage_1991 wage_1992 wage_1993 wage_1994 wage_1995 wage_1996
      <dbl>     <dbl>     <dbl>     <dbl>     <dbl>     <dbl>     <dbl>
1    13452.    13452.    13452.       NA        NA        NA        NA 
2    45000     45000     49500        NA        NA        NA        NA 
3    10302.    10302.    10302.    10302.    10302.    10302.    10302.
4       NA        NA        NA        NA        NA        NA        NA 
5       NA        NA        NA        NA        NA        NA        NA 
6     8727.     8750      8750      8750      8948.     8948.     8948.

你在哪里看到,例如第一行没有增长,也没有下降。第二排,第二年和第三年之间略有增加,但第一年和第二年为0。对于第三排,再次绝对没有变化。等等……


此外,最后,要将这些结果添加到初始数据帧中,您可以这样做,例如

df %>% 
  rowid_to_column() %>%
  left_join(growth)

为了回答性能问题,这里是一个基准测试(我将 akrun 的 data.frame 调用更改为 tibble 调用,以确保没有任何区别)。下面的所有函数都对应于创建增长率,而不是合并回原始数据帧。

library(microbenchmark)
microbenchmark(cj(), akrun(), akrun2())
Unit: microseconds
     expr      min       lq     mean   median       uq     max neval cld
     cj() 5577.301 5820.501 6122.076 5988.551 6244.301 10646.9   100   c
  akrun()  998.301 1097.252 1559.144 1160.450 1212.552 28704.5   100 a  
 akrun2() 2033.801 2157.101 2653.018 2258.052 2340.702 34143.0   100  b 

base R 在性能方面无疑是赢家。

【讨论】:

  • 这太好了,非常感谢!有没有一种有效的方法将其应用于 000 行/观察?
  • 需要多长时间?如果这真的不够快,您可以尝试 akrun 的基本 R 答案或 data.table 版本。
  • 非常感谢,我也喜欢你直观的代码!关于时间,我目前无法在工作中使用我的电脑,所以一直依赖较慢的旧电脑,再次感谢!
  • 我已经用快速基准更新了我的答案。如您所见,@akrun 的第一个答案是迄今为止最好的。
  • 哈哈哈...我觉得这很有趣,谢谢!
【解决方案2】:

我们可以使用base Rapply。循环遍历MARGIN = 1的行,去掉NA元素('x1'),得到mean的当前和前一个元素的比例

average_growth_rate <- apply(df, 1, function(x) {
        x1 <- x[!is.na(x)]
         mean(x1[-1]/x1[-length(x1)]-1)})
out <- data.frame(rowid = seq_len(nrow(df)), average_growth_rate)
out[!is.na(out$average_growth_rate),]
#    rowid average_growth_rate
#1      1       0.00000000000
#2      2       0.05000000000
#3      3       0.00000000000
#6      6       0.00422328325
#7      7       0.00008129401
#10    10       0.00354038282
#13    13       0.00000000000
#14    14       0.00000000000
#17    17       0.00000000000
#18    18       0.00000000000
#19    19       0.00000000000
#20    20       0.00000000000

或使用tapply/stack

na.omit(stack(tapply(as.matrix(df), row(df), FUN = function(x) 
     mean(head(na.omit(x), -1)/tail(na.omit(x), -1) -1))))[2:1]

【讨论】:

  • 谢谢,请查看我更新的帖子,因为我仍有一些问题。
  • @maa425 谢谢,以你的例子,我没有得到任何错误。能否请您更新一个显示问题的示例
  • @maa425 如果您可以使用给出相同错误的小示例进行更新,那么调试起来会更容易。你有没有只有NA 元素的行?
  • @maa425 在您的新示例中,只有 NA 的行。你想对这些行做什么
  • @maa425 如果您可以删除这些行,df1 &lt;- df[rowSums(is.na(df)) &lt; ncol(df),]
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-12
相关资源
最近更新 更多