#r #dataframe
#r #фрейм данных
Вопрос:
Плакат в первый раз — так что прошу прощения, если этот вопрос простой / плохо объясненный. Благодарен любому, кто может помочь или указать мне правильное направление!
Я хотел бы сделать следующее в R-фрейме данных, если это возможно:
Существующие данные
Столбец A представляет собой вектор значений, скажем, от 10 до 20.
Новые данные / столбцы
Столбец B будет представлять собой столбец A, умноженный на столбец C
Столбец C будет представлять собой столбец C минус столбец B из предыдущей строки данных, т.е. Данные $ C [-1] — данные $ B [-1], за исключением, конечно, первой строки столбца C, которой я дам фиксированное значение.
Я пробовал это как отдельные шаги, но я продолжаю перезаписывать столбцы B и C, и у меня такое чувство, что я шел по этому пути неправильно! Я мог бы поделиться своим кодом, но я думаю, что это запутало бы дело!
Заранее спасибо!
ОТРЕДАКТИРУЙТЕ, ЧТОБЫ ДОБАВИТЬ КОД:
A <- c(0.1,0.2,0.3,0.4,0.5)
df1 <- data.frame(A)
df1$B <- 0
df1$C <- 0
df1$C[1] <- 100
df2 <- df1 %>%
mutate(B = C * A,
C = lag(C-B))
РЕЗУЛЬТАТ ИЗ ВЫШЕИЗЛОЖЕННОГО
A | B | C | |
---|---|---|---|
1 | 0.1 | 10 | NA |
2 | 0.2 | 0 | 90 |
3 | 0.3 | 0 | 0 |
4 | 0.4 | 0 | 0 |
5 | 0.5 | 0 | 0 |
ОЖИДАЕМЫЙ РЕЗУЛЬТАТ
A | B | C | |
---|---|---|---|
1 | 0.1 | 10 | 100 |
2 | 0.2 | 18 | 90 |
3 | 0.3 | 21.6 | 72 |
4 | 0.4 | 20.16 | 50.4 |
5 | 0.5 | 15.12 | 30.24 |
C2 = C1 — B1 B2 = C2 * A2
Ответ №1:
Мы можем использовать accumulate
from purrr
для выполнения рекурсивного обновления
library(dplyr)
library(purrr)
tmp <- with(df1, accumulate(A, ~ .x - (.x * .y), .init = first(C)))
df2 <- df1 %>%
mutate(C = head(tmp, -1), B = -diff(tmp))
df2
# A B C
#1 0.1 10.00 100.00
#2 0.2 18.00 90.00
#3 0.3 21.60 72.00
#4 0.4 20.16 50.40
#5 0.5 15.12 30.24
Или использовать base R
tmp <- with(df1, Reduce(function(x, y) x - (x * y), A,
accumulate = TRUE, init = C[1]))
df2 <- transform(df1, C = head(tmp, -1), B = -diff(tmp))
Комментарии:
1. Спасибо! Я думаю, что я почти на месте. Я немного изменил ваш приведенный выше код на lag (C-B), см. Ниже. Однако C1 изменяется на NA (но я бы хотел, чтобы это оставалось равным 100), и я все еще получаю 0 для других значений. В идеале я хотел бы получить 18 (0,2 * 90) в B2 и 72 (90-18) в C3. И так далее. Извините, если я что-то пропустил! A <- c(0.1,0.2,0.3,0.4,0.5) df1 <- data.frame(A) df1$B <- 0 df1$C <- 0 df1$C[1] <- 100 df2 <- df1 %>% мутировать(B = C * A,C = задержка (C-B))
2. @Tyingtocode без воспроизводимого примера сложно протестировать
3. Я добавил приведенный выше код в свой первоначальный пост выше вместе с результирующей таблицей. Помогает ли это в качестве воспроизводимого примера? Единственные значения, которые я подключаю к этому тесту, — это вектор A. Еще раз спасибо!
4. @Tyingtocode можете ли вы обновить свой пост с ожидаемым результатом
5. Работает идеально! Большое спасибо!
Ответ №2:
Если вы не возражаете против использования математического подхода, вы можете сначала вывести общее выражение для рекурсии, а затем получить R-код впоследствии.
Ниже приведена одна реализация с базовым R
transform(
transform(
df1,
C = C[1] * c(1, cumprod(1 - A)[-nrow(df1)])
),
B = A * C
)
что дает
A B C
1 0.1 10.00 100.00
2 0.2 18.00 90.00
3 0.3 21.60 72.00
4 0.4 20.16 50.40
5 0.5 15.12 30.24
Аналогичным data.table
образом можно
> setDT(df1)[, C := first(C) * c(1, cumprod(1 - A)[-.N])][, B := A * C][]
A B C
1: 0.1 10.00 100.00
2: 0.2 18.00 90.00
3: 0.3 21.60 72.00
4: 0.4 20.16 50.40
5: 0.5 15.12 30.24
Комментарии:
1. Потрясающе! Спасибо за эти другие варианты!