首页 > 解决方案 > 删除 lag == 0 的成对行并使用 dplyr 和链接计算百分比变化

问题描述

我正在处理一个非常大的 tibble,并且想要计算这些表随时间的增长百分比(第一个条目到最后一个条目,而不是最大值到最小值)。我最终还希望将任何更改为 0 的表存储到它们自己的列表/小标题中,但将它们从原始输出表中删除。

数据集的示例如下所示:

  date    tbl_name    row_cnt
2/12/2019  first       247
6/5/2019   first       247
4/24/2019  second    3617138
6/5/2019   second    3680095
3/1/2019   third    62700321
6/5/2019   third    63509189
4/24/2019  fourth       2
6/5/2019   fourth       2
...          ...       ...

并且该表的预期输出将是两个表,如下所示:

tbl_name   pct_change
second       1.74
third        1.29
...          ...


tbl_name
 first
 fourth
  ...

到目前为止,我已经能够安排观察,对它们进行分组,并成功过滤每个组的第一个和最后一个实例:

test_df <- df %>% 
  arrange(l.fully_qualf_tbl_nm) %>% 
  group_by(l.fully_qualf_tbl_nm) %>%
  filter(row_number()==1 | row_number()==n()) %>%
  mutate(pct_change = ((l.row_cnt/lag(l.row_cnt) - 1) * 100)) %>% 
  select(l.run_dt, l.fully_qualf_tbl_nm, pct_change) %>% 
  drop_na(pct_change)

但我的计算

mutate(pct_change = ((l.row_cnt/lag(l.row_cnt) - 1) * 100)) %>%

没有产生正确的结果。我从另一个讨论 %-change 的 SO 帖子中提取了我的 pct-change 计算,但我从我的手工计算中得到了不同的数字。

例如,我得到“second = 3.61”,但手动计算(以及 excel)得到 1.74。我也得到“第三 = 0.831”而不是手动得到 1.29。我的猜测是我没有正确指定我只希望对每个组(每对两行)进行计算。我想知道我是否应该单独计算滞后,或者我只是错误地实施了滞后()?

接下来,我认为新表将以某种方式创建

if return value of filter(row_number()==1 | row_number()==n()) %>% == 0, append to list/table

但老实说,我不知道该怎么做。我想知道我是否应该只做一个单独的函数并将其分配给一个新变量。

标签: rdplyrpipetibble

解决方案


df <- read.table(
  header = T, 
  stringsAsFactors = F,
  text = " date    tbl_name    row_cnt
2/12/2019  first       247
6/5/2019   first       247
4/24/2019  second    3617138
6/5/2019   second    3680095
3/1/2019   third    62700321
6/5/2019   third    63509189
4/24/2019  fourth       2
6/5/2019   fourth       2")

# Wrapping in parentheses assigns the output to test_df and also prints it
(test_df <- df %>% 
    group_by(tbl_name) %>%
    mutate(pct_change = ((row_cnt/lag(row_cnt) - 1) * 100)) %>% 
    ungroup() %>%
    filter(!is.na(pct_change)) %>%  # Filter after pct_change calc, since we want to 
                                    # include change from 1:2  and from n-1:n
    select(tbl_name, row_cnt, pct_change))

# A tibble: 4 x 3
  tbl_name  row_cnt pct_change
  <chr>       <int>      <dbl>
1 first         247       0   
2 second    3680095       1.74
3 third    63509189       1.29
4 fourth          2       0  

要分成两张表,似乎可以这样做:

first_tbl <- test_df %>% filter(pct_change != 0) # or "pct_change > 0" for pos growth
second_tbl <- test_df %>% filter(pct_change == 0)

推荐阅读