вычитание значения из значения выше автоматически - без цикла - PullRequest
1 голос
/ 31 января 2020

Я пытаюсь получить значение баланса от df, который выглядит следующим образом

df1
Name   Year    Ch1    Origin
A      1995    x1      a
A      1996    x2      b
A      1997    x3      a
A      2000    x4      a
B      1997    y1      c
B      1998    y2      c
.....

, в то время как Ch1 является числовым. и я хочу добавить дополнительный столбец, чтобы иметь это значение:

Name   Year   Ch1    Bil
A      1995    x1    
A      1996    x2    %of year before (x2-x1/x1*100)%
A      1997    x3    %of year before (x3-x2/x2*100)%
A      2000    x4    %of year before (x4-x3/x3*100)%
B      1997    y1  
B      1998    y2    %of year before (y2-y1/x1*100)%
.....

теперь я знаю, что мог бы создать al oop, выглядящий примерно так:

for (i in nrow(df1))
  if (df[i,1]==df[i-1,1]) {
    df$Bil<-(df[i,3]-df[i-1,3])/df[i-1,3]*100
  } else ...

Есть ли еще элегантный или более быстрый способ рассчитать это? Таким образом, мне действительно нужно убедиться, что набор данных находится в правильном порядке (начиная с более старых до последних лет). Допустим, также зависит от дополнительных деталей, таких как происхождение, так что расчет происходит только в том случае, если имя и происхождение совпадают?

Спасибо!

1 Ответ

2 голосов
/ 31 января 2020

Все три решения требуют, чтобы данные были в правильном порядке в каждом Name. Например, вы можете чередовать имена «A» и «B» (все группы ниже будут обрабатывать это), но годы, вероятно, должны быть неубывающими. 1005 *

set.seed(42)
df1$Ch1 <- c(sort(sample(20, size=4)), sort(sample(20, size=2)))

База R

df1 <- df1[order(df1$Name, df1$Year),]
df1$Bil <- ave(df1$Ch1, df1$Name, df1$Origin,
               FUN=function(z) 100 * c(0, diff(z) / head(z, n = -1)))
df1
#   Name Year Ch1 Origin        Bil
# 1    A 1995   6      a   0.000000
# 2    A 1996  15      b   0.000000
# 3    A 1997  18      a 200.000000
# 4    A 2000  19      a   5.555556
# 5    B 1997  10      c   0.000000
# 6    B 1998  13      c  30.000000

dplyr

library(dplyr)
df1 %>%
  arrange(Name, Year) %>%
  group_by(Name, Origin) %>%
  mutate(
    Bil = 100 * c(0, diff(Ch1) / head(Ch1, n = -1))
  ) %>%
  ungroup()

data.table

library(data.table)
library(magrittr)
df1DT <- as.data.table(df1)
setorder(df1DT, Name, Year)
df1DT[, Bil := 100 * c(0, diff(Ch1) / head(Ch1, n = -1)), by = .(Name, Origin)]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...