Это подход, при котором мы создаем узкий формат данных для запуска, а затем используем pivot_wider()
, чтобы получить результат со столбцами Length
и Width
.
library(tidyr)
# add an ID variable so we can pivot_wider and match measurement for correct observations
id <- 1:nrow(iris)
data <- cbind(id,iris)
data %>% gather(.,key = "part.measurement",value = "value",-id,-Species) %>%
separate(.,part.measurement,c("part","measurement")) -> narrow_data
head(narrow_data[2:5])
> head(narrow_data[2:5])
Species part measurement value
1 setosa Sepal Length 5.1
2 setosa Sepal Length 4.9
3 setosa Sepal Length 4.7
4 setosa Sepal Length 4.6
5 setosa Sepal Length 5.0
6 setosa Sepal Length 5.4
На данный момент мы можем использовать pivot_wider()
для создания столбцов Length
и Width
. Мы добавим arrange()
, чтобы порядок сортировки соответствовал изображению с вопросом.
narrow_data %>% pivot_wider(.,names_from = measurement,values_from = value) %>%
arrange(Species,part)-> wide_data
head(wide_data[2:5])
... и вывод:
> head(wide_data[2:5])
# A tibble: 6 x 4
Species part Length Width
<fct> <chr> <dbl> <dbl>
1 setosa Petal 1.4 0.2
2 setosa Petal 1.4 0.2
3 setosa Petal 1.3 0.2
4 setosa Petal 1.5 0.2
5 setosa Petal 1.4 0.2
6 setosa Petal 1.7 0.4
>
Второй вывод сложный, поскольку он по существу объединяет 200 наблюдений детали и измерения для каждого вида цветка в выходной столбик 200 строк, по одной для каждой комбинации part
и length
для каждого из 50 наблюдений каждого Species
.
# reproduce 2nd output
speciesId <- c(1:200,1:200,1:200) # unique obs within species
narrow_species_data <- cbind(speciesId,narrow_data[order(narrow_data[,1],narrow_data[,3],narrow_data[,4]),c(2:5)])
narrow_species_data %>% pivot_wider(.,names_from= Species,values_from = value) %>%
arrange(part,measurement,speciesId) -> wide_data_species
head(wide_data_species[2:6])
... и вывод:
> head(wide_data_species[2:6])
# A tibble: 6 x 5
part measurement setosa versicolor virginica
<chr> <chr> <dbl> <dbl> <dbl>
1 Petal Length 1.4 4.7 6
2 Petal Length 1.4 4.5 5.1
3 Petal Length 1.3 4.9 5.9
4 Petal Length 1.5 4 5.6
5 Petal Length 1.4 4.6 5.8
6 Petal Length 1.7 4.5 6.6
>
"полностью измененная" версия
Вот версия обеих частей вопроса, которая использует исключительно функции из семейства пакетов tidyverse
.
Для первого вопроса мы используем mutate()
и seq_along()
, чтобы создать уникальные последовательные числа для идентификации каждого наблюдения в исходных данных. Мы создаем набор данных узкой формы с помощью gather()
, а затем преобразуем его в желаемый результат с помощью pivot_wider()
. Чтобы сопоставить порядок наблюдений с изображения в исходном вопросе, мы arrange(Species,part)
.
library(tidyr)
library(dplyr)
# add an ID variable so we can pivot_wider and match measurement for correct observations
iris %>% mutate(id = seq_along(Species)) %>% gather(.,key = "part.measurement",value = "value",-id,-Species) %>%
separate(.,part.measurement,c("part","measurement")) -> narrow_data
narrow_data %>% pivot_wider(.,names_from = measurement,values_from = value) %>%
arrange(Species,part) -> wide_data
head(wide_data[2:5])
... и вывод:
> head(wide_data[2:5])
# A tibble: 6 x 4
id part Length Width
<int> <chr> <dbl> <dbl>
1 1 Petal 1.4 0.2
2 2 Petal 1.4 0.2
3 3 Petal 1.3 0.2
4 4 Petal 1.5 0.2
5 5 Petal 1.4 0.2
6 6 Petal 1.7 0.4
>
Для второго вопроса вместо построения вектора последовательных идентификаторов для каждого вида и использования cbind()
для остальных данных, мы можем использовать функции dplyr
для создания последовательностей в конвейере.
Мы используем arrange()
для сортировки данных по видам, идентификаторам, деталям и измерениям. Затем мы group_by(Species)
, поэтому мы можем использовать mutate()
для создания уникального последовательного идентификатора с seq_along()
. Порядок сортировки важен, потому что мы хотим объединить 1-е наблюдение с 51-м наблюдением и 101-м наблюдением.
Затем мы ungroup()
очищаем group_by()
и используем pivot_wider()
с id_cols = speciesId
для создания желаемого результата.
narrow_data %>% arrange(Species,id,part,measurement) %>% group_by(Species) %>% mutate(speciesId = seq_along(Species)) %>%
ungroup(.) %>% pivot_wider(.,id_cols=c("speciesId","part","measurement"),names_from= Species,values_from = value) %>%
arrange(part,measurement,speciesId) -> wide_data_species
head(wide_data_species[2:6])
... и вывод:
> head(wide_data_species[2:6])
# A tibble: 6 x 5
part measurement setosa versicolor virginica
<chr> <chr> <dbl> <dbl> <dbl>
1 Petal Length 1.4 4.7 6
2 Petal Length 1.4 4.5 5.1
3 Petal Length 1.3 4.9 5.9
4 Petal Length 1.5 4 5.6
5 Petal Length 1.4 4.6 5.8
6 Petal Length 1.7 4.5 6.6
>