以长格式向数据框添加行

时间:2018-05-17 06:26:00

标签: r dataframe dplyr

给出如下所示的数据框df

text <- "
parameter,car,qtr,val
a,a3,FY18Q1,23
b,a3,FY18Q1,10000
a,a3,FY18Q2,14
b,a3,FY18Q2,12000
a,cla,FY18Q1,15
b,cla,FY18Q1,12000
c,cla,FY18Q1,5.5
a,cla,FY18Q2,26
b,cla,FY18Q2,10000
c,cla,FY18Q2,6.2
"
df <- read.table(textConnection(text), sep = ",", header = TRUE)

我想为每个b_diff组合添加一个参数car, qtr的行,val作为两个连续b的参数qtr的差异。 qtr升序为FY18Q1, FY18Q2。对于qtr的第一个FY18Q1val的{​​{1}}应为NA,因为没有b_diff previous

预期输出如下。

qtr

如何使用parameter car qtr val a a3 FY18Q1 23 b a3 FY18Q1 10000 b_diff a3 FY18Q1 NA a a3 FY18Q2 14 b a3 FY18Q2 12000 b_diff a3 FY18Q2 2000 a cla FY18Q1 15 b cla FY18Q1 12000 c cla FY18Q1 5.5 b_diff cla FY18Q1 NA a cla FY18Q2 26 b cla FY18Q2 10000 c cla FY18Q2 6.2 b_diff cla FY18Q2 -2000 执行此操作?

2 个答案:

答案 0 :(得分:2)

使用的解决方案。我们可以使用group_indices创建一个组ID,并根据它来拆分数据框,汇总数据然后将它们组合起来。 df5是最终输出。

library(dplyr)
library(purrr)

df2 <- df %>% mutate(GroupID = group_indices(., car, qtr))

df3 <- df2 %>%
  filter(parameter %in% "b") %>%
  group_by(car) %>%
  mutate(val = val - lag(val), parameter = "b_diff") %>%
  ungroup() %>%
  split(f = .$GroupID)

df4 <- df2 %>% split(f = .$GroupID)

df5 <- map2_dfr(df4, df3, bind_rows) %>% select(-GroupID)

df5
#    parameter car    qtr     val
# 1          a  a3 FY18Q1    23.0
# 2          b  a3 FY18Q1 10000.0
# 3     b_diff  a3 FY18Q1      NA
# 4          a  a3 FY18Q2    14.0
# 5          b  a3 FY18Q2 12000.0
# 6     b_diff  a3 FY18Q2  2000.0
# 7          a cla FY18Q1    15.0
# 8          b cla FY18Q1 12000.0
# 9          c cla FY18Q1     5.5
# 10    b_diff cla FY18Q1      NA
# 11         a cla FY18Q2    26.0
# 12         b cla FY18Q2 10000.0
# 13         c cla FY18Q2     6.2
# 14    b_diff cla FY18Q2 -2000.0

数据

请注意,最好拥有stringsAsFactors = FALSE

text <- "
parameter,car,qtr,val
a,a3,FY18Q1,23
b,a3,FY18Q1,10000
a,a3,FY18Q2,14
b,a3,FY18Q2,12000
a,cla,FY18Q1,15
b,cla,FY18Q1,12000
c,cla,FY18Q1,5.5
a,cla,FY18Q2,26
b,cla,FY18Q2,10000
c,cla,FY18Q2,6.2
"
df <- read.table(textConnection(text), sep = ",", header = TRUE, stringsAsFactors = FALSE)

答案 1 :(得分:1)

这是一种算法:

  1. 将数据重塑为&#34; wide&#34;格式,以便qtrcar形成一个唯一的行索引,parameter列&#34;传播&#34;到列
  2. 在每个汽车价值中,采用新parameter_b
  3. 的1期差异
  4. 将数据重新整形为&#34; long&#34;格式
  5. 使用reshape2和dplyr的等效代码:

    # optional. you could just use `c(NA, diff(x))` below, but this is more general
    padded_diff <- function(x, lag = 1L) {
      c(rep.int(NA, lag), diff(x, lag = lag))
    }
    
    df %>%
      dcast(car + qtr ~ parameter, value.var = "val") %>%
      mutate(b_diff = padded_diff(b)) %>%
      melt(id.vars = c("car", "qtr"), variable.name = "parameter") %>%
      arrange(car, qtr, parameter)
    

    这是另一种算法:

    1. car
    2. 对数据框进行分组
    3. 在每个组中,暂时过滤,以便只显示paramter == "b"的行
    4. 采用val
    5. 的1期差异
    6. 删除过滤器并取消组合
    7. 等效代码,仅使用dplyr,使用临时表来模拟&#34;可移动的&#34;过滤器:

      make_b_diff_within_group <- function(df) {
        tmp <- df %>%
          filter(parameter == "b") %>%
          transmute(
            qtr = qtr,
            val = padded_diff(val),
            parameter = "b_diff")
      
        bind_rows(df, tmp)
      }
      
      df %>%
        group_by(car) %>%
        do(make_b_diff_within_group(.)) %>%
        ungroup() %>%
        arrange(car, qtr, parameter)
      

      这个第二个算法可以使用其他几个&#34; split-apply-combine&#34;范例,包括基R中的tapplyby函数,plyr包中的ddply函数(同一作者的dplyr的祖先)和split方法来自dplyr,如this answer所示。