Добавьте каждые три строки фрейма данных и умножьте их на новые результаты - R - PullRequest
2 голосов
/ 12 июня 2019

У меня есть фрейм данных, и я хотел бы добавить его каждые три строки. Затем примените cumprod к строкам, чтобы получить новый data.frame с результирующими новыми строками.

В конце у меня будет только одна треть от числа строк.

Ниже вы можете найти код, который я написал. Я попытался найти класс объектов и скопировать код, который работал для вектора, а не матрицы.

    XYZ<-read.xlsx2("XYZ.xlsx",1)
    XYZ.CUT<-aggregate(XYZ~gl(nrow(XYZ)/3, 3), data.frame(XYZ), sum)
    F.XYZ<-apply(t(XYZ.CUT+1),1,cumprod)

Вот что у меня есть:

 X       Y      Z 
-0,01%   0,32%  0,11%
-0,04%   0,01%  0,45%
-0,11%  -0,06%  0,03%
 0,03%  -0,04%  0,45%
 0,02%   0,04%  0,30%
-0,07%  -0,11%  0,11%
-0,12%  -0,13%  0,30%
-0,01%  -0,07%  0,04%
-0,37%   0,08%  0,05%

сначала хочу:

 X       Y      Z
-0,16%   0,25%  0,59%
-0,02%  -0,11%  0,86%
-0,50%  -0,12%  0,39%

и после добавления 1 к каждому элементу:

 X           Y           Z
(1-0,16%)   (1+0,25%)   (1+0,59%)
(1-0,02%)   (1-0,11%)   (1+0,86%)
(1-0,50%)   (1-0,12%)   (1+0,39%)

Я хотел бы сделать комет из строк:

X           Y           Z
x1          y1          z1
x1*x2       y1*y2       z1*z2
x1*x2*x3    y1*y2*y3    z1*z2*z3

Расширенные приветствия.

Ответы [ 3 ]

2 голосов
/ 12 июня 2019

Мы можем использовать tidyverse. Используя parse_number из readr, извлеките числовую часть из столбцов (mutate_all), сгруппированных по индексу, созданному с помощью gl, summarise всех столбцов, чтобы получить sum

library(tidyverse)
library(readr)
out <- XYZ %>% 
          mutate_all(parse_number) %>%
          group_by(grp = as.integer(gl(n(), 3, n()))) %>%
          summarise_all(sum)   

Затем мы используем rowCumprods из matrixStats, чтобы получить совокупный продукт каждой строки

library(matrixStats)
rowCumprods(as.matrix(out[-1]) + 1) 
#     [,1]   [,2]     [,3]
#[1,] 0.84 1.0668 1.696212
#[2,] 0.98 0.8722 1.622292
#[3,] 0.50 0.4400 0.611600

данные

XYZ <- structure(list(X = c("-0.01%", "-0.04%", "-0.11%", "0.03%", "0.02%", 
"-0.07%", "-0.12%", "-0.01%", "-0.37%"), Y = c("0.32%", "0.01%", 
"-0.06%", "-0.04%", "0.04%", "-0.11%", "-0.13%", "-0.07%", "0.08%"
), Z = c("0.11%", "0.45%", "0.03%", "0.45%", "0.30%", "0.11%", 
"0.30%", "0.04%", "0.05%")), row.names = c(NA, -9L), class = "data.frame")
1 голос
/ 12 июня 2019

Другая базовая версия R, использующая rowsum для получения агрегированных сумм (используя набор данных @ Akrun's XYZ):

XYZ[] <- lapply(XYZ, sub, pat="%$", rep="")
XYZ[] <- lapply(XYZ, as.numeric)

out <- rowsum(XYZ, (seq_len(nrow(XYZ)) + 2) %/% 3) + 1

Затем выберите свое приключение в зависимости от того, каким образом вы хотитесовокупный продукт для работы:

## column-wise cumprod

out[] <- lapply(out, cumprod)
out
#       X        Y        Z
#1 0.8400 1.270000 1.590000
#2 0.8232 1.130300 2.957400
#3 0.4116 0.994664 4.110786

## row-wise cumprod

out[] <- Reduce(`*`, out, accumulate=TRUE)
out
#     X      Y        Z
#1 0.84 1.0668 1.696212
#2 0.98 0.8722 1.622292
#3 0.50 0.4400 0.611600
1 голос
/ 12 июня 2019

Мы можем сделать это следующим образом, используя только базу R:

#First remove the % symbol from the columns and convert the values to numeric
XYZ[] <- lapply(XYZ, function(x) as.numeric(sub("%", "", x)))

#Sum every 3 rows
XYZ.CUT <- aggregate(.~ gl(nrow(XYZ)/3, 3),XYZ, sum)[-1]

#Add 1 and take cumulative product for each row
t(apply(XYZ.CUT + 1, 1, cumprod))
#Or if you need it columnwise use 
#apply(XYZ.CUT + 1, 2, cumprod) 
#        X      Y        Z
#[1,] 0.84 1.0668 1.696212
#[2,] 0.98 0.8722 1.622292
#[3,] 0.50 0.4400 0.611600
...