добавление строки во фрейм данных в длинном формате - PullRequest
0 голосов
/ 17 мая 2018

С учетом кадра данных 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, который является FY18Q1, val для b_diff должно быть NA, поскольку 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

Как мне сделать это с dplyr?

Ответы [ 2 ]

0 голосов
/ 17 мая 2018

Вот один алгоритм:

  1. Преобразование данных в «широкий» формат, так что qtr и car образуют уникальный индекс строки, а столбец parameter «распределяется» по столбцам
  2. В пределах каждого значения автомобиля возьмите 1-периодный дифференциал нового столбца parameter_b
  3. Преобразовать данные обратно в «длинный» формат

Эквивалентный код с использованием 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. В каждой группе временно отфильтруйте, чтобы присутствовали только строки с paramter == "b"
  3. Возьмите 1-периодный дифференциал столбца val
  4. Снять фильтр и разгруппировать

Эквивалентный код, используя только dplyr, используя временную таблицу для имитации «съемного» фильтра:

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)

Этот второй алгоритм может быть реализован с использованием нескольких других парадигм «разбить-применить-объединить», включая функции tapply или by в base R, функцию ddply в пакете plyr (предок dplyr от того же автора) и метод split от dplyr, как показано в этот ответ .

0 голосов
/ 17 мая 2018

Решение с использованием и . Мы можем создать идентификатор группы, используя group_indices и основываясь на этом, чтобы разделить фрейм данных, суммировать данные и затем объединить их. 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

DATA

Обратите внимание, что лучше иметь 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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...