Примените условную функцию в каждой строке фрейма данных - PullRequest
0 голосов
/ 22 апреля 2019

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

Date      Group       Factor 1 Factor 2 Spread
2019-04-01  a   1.01    1.011   0.01
2019-04-02  a   1.02    1.012   0.02
2019-04-03  a   1.03    1.013   0.03
2019-04-01  b   1.005   1.004   0.01
2019-04-02  b   1.0051  1.0041  0.02
2019-04-03  b   1.0052  1.0042  0.03

Я хотел бы проверить каждую группу в каждой строке, и если результаты - это группа "a"делайте Factor1 / Factor1 (лаг 1 день) * Factor2 + спред, и если группа не является "a", не добавляйте спред.

1 Ответ

0 голосов
/ 23 апреля 2019

Поскольку вы тренируете группу, это хороший пример by (база R), dplyr::group_by или data.table * x[,,by=].

Уравнение эффективното же самое во всех трех, используя тот факт, что (Group[1] == "a") будет приведен от logical до numeric при умножении на число;поскольку FALSE переводит в 0, то фактически отключается, добавляя Spread.

Base

Я использую within здесь, чтобы сделать внутреннюю часть немного более читабельной, но это нетребование (в этом случае вам нужно будет добавить x$ перед всеми именами переменных).

Отставание может быть сделано с помощью dplyr::lag (даже если вы не используете остальныепакет для этого) или многие другие методы.Я не считаю stats::lag наиболее интуитивным в подобных приложениях, но я уверен, что кто-нибудь предложит способ включить его в ответ.Использование c(NA, ...) гарантирует, что мы не будем вводить данные другой группы или вменять данные, которых у нас нет, поскольку у нас нет никакой ценности вводить в первый ряд группы.Наконец, head(..., n = 1) возвращает первый элемент вектора / списка, а head(..., n = -1) (отрицательный) возвращает все, кроме последнего .

newx <- by(x, x$Group, function(y) {
  within(y, {
    NewVal = Factor2 * Factor1 / c(NA, head(Factor1, n=-1)) + (Group[1] == "a") * Spread
  })
})
newx
# x$Group: a
#         Date Group Factor1 Factor2 Spread   NewVal
# 1 2019-04-01     a    1.01   1.011   0.01       NA
# 2 2019-04-02     a    1.02   1.012   0.02 1.042020
# 3 2019-04-03     a    1.03   1.013   0.03 1.052931
# -------------------------------------------------------
# x$Group: b
#         Date Group Factor1 Factor2 Spread NewVal
# 4 2019-04-01     b  1.0050  1.0040   0.01     NA
# 5 2019-04-02     b  1.0051  1.0041   0.02 1.0042
# 6 2019-04-03     b  1.0052  1.0042   0.03 1.0043

Это действительно просто list с каким-то необычным by -специфическим форматированием, так что вы можете рассматривать его как таковое или комбинировать их эффективным способом base-R:

do.call("rbind.data.frame", c(newx, stringsAsFactors = FALSE))
#           Date Group Factor1 Factor2 Spread   NewVal
# a.1 2019-04-01     a  1.0100  1.0110   0.01       NA
# a.2 2019-04-02     a  1.0200  1.0120   0.02 1.042020
# a.3 2019-04-03     a  1.0300  1.0130   0.03 1.052931
# b.4 2019-04-01     b  1.0050  1.0040   0.01       NA
# b.5 2019-04-02     b  1.0051  1.0041   0.02 1.004200
# b.6 2019-04-03     b  1.0052  1.0042   0.03 1.004300

dplyr

Многие находятtidyverse Линия пакетов для интуитивного чтения.

library(dplyr)
x %>%
  group_by(Group) %>%
  mutate(NewVal = Factor2 * Factor1 / lag(Factor1) + (Group[1] == "a") * Spread) %>%
  ungroup()
# # A tibble: 6 x 6
#   Date       Group Factor1 Factor2 Spread NewVal
#   <chr>      <chr>   <dbl>   <dbl>  <dbl>  <dbl>
# 1 2019-04-01 a        1.01    1.01   0.01  NA   
# 2 2019-04-02 a        1.02    1.01   0.02   1.04
# 3 2019-04-03 a        1.03    1.01   0.03   1.05
# 4 2019-04-01 b        1.00    1.00   0.01  NA   
# 5 2019-04-02 b        1.01    1.00   0.02   1.00
# 6 2019-04-03 b        1.01    1.00   0.03   1.00

data.table

С другой стороны, многие находят data.table лучше из-за эффективности, получаемой от модификации на месте (большинствоиз операций R являются копированием при записи, что означает, что некоторые операции повторно копируют объект или его часть при каждом изменении).

library(data.table)
X <- as.data.table(x)
X[, NewVal := Factor2 * Factor1 / shift(Factor1) + (Group[1] == "a") * Spread, by = "Group"]
X
#          Date Group Factor1 Factor2 Spread   NewVal
# 1: 2019-04-01     a  1.0100  1.0110   0.01       NA
# 2: 2019-04-02     a  1.0200  1.0120   0.02 1.042020
# 3: 2019-04-03     a  1.0300  1.0130   0.03 1.052931
# 4: 2019-04-01     b  1.0050  1.0040   0.01       NA
# 5: 2019-04-02     b  1.0051  1.0041   0.02 1.004200
# 6: 2019-04-03     b  1.0052  1.0042   0.03 1.004300

Часть «на месте» видна во второй строкездесь, где это выглядит так, как будто операция [ должна просто возвращать подмножество или что-то из данных ... но в этом случае использование := вызывает создание (или изменение) столбцов на месте.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...