Упорядочить данные по идентификатору, а затем по дате и найти разницу в R - PullRequest
0 голосов
/ 12 января 2020

Я пытаюсь организовать большое количество данных сначала по уникальному идентификатору, а затем по дате, чтобы найти разницу между днями и днями.

Пример моих данных показан ниже:

date        id       value1    value2
1/1/2019   1234       10         12
1/2/2019   1234       11         14
1/3/2019   1234       12         15
1/1/2019   9876       9          10
1/2/2019   9876       11         12
1/3/2019   9876       6          9

Что бы я хотел сделать sh, это найти разницу между датами для данного идентификатора. Пример выходного столбца будет выглядеть следующим образом:

date        id       value1    value2    difference       change
1/1/2019   1234       10         12          0              0
1/2/2019   1234       11         14         11-12          -1/12
1/3/2019   1234       12         15         12-14          -2/14
1/1/2019   9876       9          10          0              0
1/2/2019   9876       11         12         11-10           1/10
1/3/2019   9876       6          9           6-12          -6/12

Вопросы: сначала как отсортировать данные по идентификатору, а затем по дате? Во-вторых, как рассчитать разницу для каждой следующей даты для данного идентификатора?

Спасибо!

Ответы [ 2 ]

4 голосов
/ 12 января 2020

Мы можем сделать группу по 'id' и получить diff из 'value'

library(dplyr)
df1 <- df1 %>%
          group_by(id) %>%
          mutate(difference = c(0, diff(value)))
df1
# A tibble: 6 x 4
# Groups:   id [2]
#  date        id value difference
#  <chr>    <int> <int>      <dbl>
#1 1/1/2019  1234    10          0
#2 1/2/2019  1234    11          1
#3 1/3/2019  1234    12          1
#4 1/1/2019  9876     9          0
#5 1/2/2019  9876    11          2
#6 1/3/2019  9876     6         -5

Здесь «date» уже arrange d, если нет, то сделать arrange после преобразования в Date класс (при условии, что форматом является день-месяц-год)

library(lubridate)
df1 %>%
   arrange(id, dmy(date)) %>%
   group_by(id) %>%
   mutate(difference = c(0, diff(value)))

Обновление

С новым набором данных, после группировки по 'id', мы можем получить разницу между текущим элементом 'value1' с lag для 'value2' и получить change, разделив столбец 'разности' на lag столбец

df2 %>%
   arrange(id, dmy(date)) %>%
   group_by(id) %>%
   mutate(lagvalue2 = lag(value2, default = first(value1))) %>%
   ungroup %>%
   mutate(difference = value1  - lagvalue2, 
          change = difference/lagvalue2) %>%
   select(-lagvalue2)
# A tibble: 6 x 6
#  date        id value1 value2 difference  change
#  <chr>    <int>  <int>  <int>      <int>   <dbl>
#1 1/1/2019  1234     10     12          0  0     
#2 1/2/2019  1234     11     14         -1 -0.0833
#3 1/3/2019  1234     12     15         -2 -0.143 
#4 1/1/2019  9876      9     10          0  0     
#5 1/2/2019  9876     11     12          1  0.1   
#6 1/3/2019  9876      6      9         -6 -0.5   

Или используя data.table

library(data.table)
setDT(df2)[order(dmy(date)), lagvalue2 := shift(value2, fill = first(value1)) , id]
df2[, difference := value1 - lagvalue2][, change := difference/lagvalue2]

В base R мы можем сделать

df1 <- df1[order(df1$id, as.Date(df1$date, "%d/%m/%Y")),]
df1$difference <- with(df1, ave(value, id, FUN = function(x) c(0, diff(x))))

data

df1 <- structure(list(date = c("1/1/2019", "1/2/2019", "1/3/2019", "1/1/2019", 
"1/2/2019", "1/3/2019"), id = c(1234L, 1234L, 1234L, 9876L, 9876L, 
9876L), value = c(10L, 11L, 12L, 9L, 11L, 6L)), class = "data.frame", 
row.names = c(NA, 
-6L))



df2 <- structure(list(date = c("1/1/2019", "1/2/2019", "1/3/2019", "1/1/2019", 
"1/2/2019", "1/3/2019"), id = c(1234L, 1234L, 1234L, 9876L, 9876L, 
9876L), value1 = c(10L, 11L, 12L, 9L, 11L, 6L), value2 = c(12L, 
14L, 15L, 10L, 12L, 9L)), class = "data.frame", row.names = c(NA, 
-6L))
1 голос
/ 12 января 2020

Вот базовое решение R, которое использует split() + Map() + rbind():

dfout <- do.call(rbind, c(make.row.names = F,
                       Map(function(v) cbind(x <- v[order(as.Date(v$date,"%d/%m/%Y")),],
                                             difference = c(0,x$value1[-1] - x$value2[-nrow(x)]),
                                             change = c(0,x$value1[-1] - x$value2[-nrow(x)])/c(1,x$value2[-nrow(x)])), 
                           split(df,df$id))))

, такое что

> dfout
      date   id value1 value2 difference      change
1 1/1/2019 1234     10     12          0  0.00000000
2 1/2/2019 1234     11     14         -1 -0.08333333
3 1/3/2019 1234     12     15         -2 -0.14285714
4 1/1/2019 9876      9     10          0  0.00000000
5 1/2/2019 9876     11     12          1  0.10000000
6 1/3/2019 9876      6      9         -6 -0.50000000
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...