Я хотел бы рассчитать разницу между последовательными столбцами в диапазоне столбцов, используя dplyr.
Например, используя набор данных радужная оболочка, я хотел бы указать диапазон Чашелистик.Ширина:Лепесток.Ширина и иметь фрейм данных, содержащий исходные данные радужная оболочка и различия между последовательными столбцами из Sepal.Width:Petal.Width:
Sepal.Length Sepal.Width Petal.Length Petal.Width Species diff1 diff2
1 5.1 3.5 1.4 0.2 setosa 2.1 1.2
2 4.9 3.0 1.4 0.2 setosa 1.6 1.2
3 4.7 3.2 1.3 0.2 setosa 1.9 1.1
4 4.6 3.1 1.5 0.2 setosa 1.6 1.3
5 5.0 3.6 1.4 0.2 setosa 2.2 1.2
6 5.4 3.9 1.7 0.4 setosa 2.2 1.3
Кто-то выложил решение loops и lapply (Вычислить разницу между последовательными сгруппированными столбцами в таблице данных.), но я специально ищу решение dplyr.
Вот вариант с tidyverse
. Мы select
диапазон столбцов, удаляем первый и последний столбцы в list
data.frames, затем используем reduce
, чтобы получить разницу между наборами наборов данных одинакового измерения, и переименовываем столбцы.
library(dplyr)
library(purrr)
library(stringr)
out <- iris %>%
select(Sepal.Width:Petal.Width) %>%
{list(.[-length(.)], .[-1])} %>%
reduce(`-`) %>%
rename_all(~ str_c("diff", seq_along(.))) %>%
bind_cols(iris, .)
head(out)
# Sepal.Length Sepal.Width Petal.Length Petal.Width Species diff1 diff2
#1 5.1 3.5 1.4 0.2 setosa 2.1 1.2
#2 4.9 3.0 1.4 0.2 setosa 1.6 1.2
#3 4.7 3.2 1.3 0.2 setosa 1.9 1.1
#4 4.6 3.1 1.5 0.2 setosa 1.6 1.3
#5 5.0 3.6 1.4 0.2 setosa 2.2 1.2
#6 5.4 3.9 1.7 0.4 setosa 2.2 1.3
Или другой подход состоит в том, чтобы перебрать индекс столбцов select
столбцы, reduce
его в один столбец с -
и связать с исходным набором данных.
map_dfc(3:4, ~ iris %>%
select(.x-1, .x) %>%
transmute(diff = reduce(., `-`))) %>%
bind_cols(iris, .)
Не могли бы вы перечислить здесь конкретные необходимые пакеты? Похоже на dplyr
, purrr
и stringr
.
Вот менее сложный подход с использованием глаголов dplyr
и tidyr
. Сначала я собираю столбцы для дифференцирования в длинный формат, затем беру их отличия от предыдущего столбца, удаляю NA для первых столбцов, у которых нет предыдущего столбца, переименовываю столбец, распределяю и присоединяю к оригиналу.
library(tidyverse)
iris %>%
bind_cols(iris %>%
rowid_to_column() %>%
gather(col, val, Sepal.Width:Petal.Width) %>%
group_by(rowid) %>%
mutate(val = abs(val - lag(val))) %>%
filter(!is.na(val)) %>%
mutate(col = paste0("diff_", col)) %>%
spread(col, val) %>%
select(contains("diff"))
)
Sepal.Length Sepal.Width Petal.Length Petal.Width Species rowid diff_Petal.Length diff_Petal.Width
1 5.1 3.5 1.4 0.2 setosa 1 2.1 1.2
2 4.9 3.0 1.4 0.2 setosa 2 1.6 1.2
3 4.7 3.2 1.3 0.2 setosa 3 1.9 1.1
4 4.6 3.1 1.5 0.2 setosa 4 1.6 1.3
5 5.0 3.6 1.4 0.2 setosa 5 2.2 1.2
6 5.4 3.9 1.7 0.4 setosa 6 2.2 1.3
7 4.6 3.4 1.4 0.3 setosa 7 2.0 1.1
Вы также можете использовать grepl
и which
, чтобы получить индексы столбцов.
start <- which(grepl("Sepal.Width", colnames(iris)))
end <- which(grepl("Petal.Width", colnames(iris)))
for (i in start:(end-1)) {
eval(parse(text = paste0("iris$diff",i-1," <- iris[,",i,"]-iris[,",i,"+1]")))
}
спасибо @jgjiggle, но я искал решение dplyr
Указанный диапазон начинается с Sepal.Width, поэтому первая разница составляет 3,5–1,4.