сбор данных радужной оболочки. в R - PullRequest
1 голос
/ 29 марта 2020

Я хочу изменить набор данных радужной оболочки в R. Он имеет 5 переменных: разновидности, sepal.length, sepal.width, petal.length и petal.width. Мне нужен новый столбец с именем part, который указывает, являются ли столбцы чашелистика или лепестка, а также длины и ширины, которые показывают измерения. результат должен выглядеть следующим образом:

image

Мне также нужно сделать еще один, где есть столбец с именем меры, который указывает тип измерения (длина или ширина) и показывает с виды как переменные. Это должно выглядеть так:

Как мне это сделать с помощью tidyr?

Ответы [ 3 ]

2 голосов
/ 29 марта 2020

Это подход, при котором мы создаем узкий формат данных для запуска, а затем используем 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
>
1 голос
/ 30 марта 2020

Это можно сделать только с помощью tidyr функций:

Первый шаг:

(first <- iris %>%
  pivot_longer(cols = -Species, names_sep = "\\.", names_to = c("Part", ".value")))

# A tibble: 300 x 4
   Species Part  Length Width
   <fct>   <chr>  <dbl> <dbl>
 1 setosa  Sepal    5.1   3.5
 2 setosa  Petal    1.4   0.2
 3 setosa  Sepal    4.9   3  
 4 setosa  Petal    1.4   0.2
 5 setosa  Sepal    4.7   3.2
 6 setosa  Petal    1.3   0.2
 7 setosa  Sepal    4.6   3.1
 8 setosa  Petal    1.5   0.2
 9 setosa  Sepal    5     3.6
10 setosa  Petal    1.4   0.2
# ... with 290 more rows

Второй шаг:

first %>%
   pivot_longer(cols = c(Length, Width), names_to = "Measure") %>%
   pivot_wider(names_from = Species, values_from = value, values_fn = list(value = list)) %>%
   unnest(cols = -c(Part, Measure))

# A tibble: 200 x 5
   Part  Measure setosa versicolor virginica
   <chr> <chr>    <dbl>      <dbl>     <dbl>
 1 Sepal Length     5.1        7         6.3
 2 Sepal Length     4.9        6.4       5.8
 3 Sepal Length     4.7        6.9       7.1
 4 Sepal Length     4.6        5.5       6.3
 5 Sepal Length     5          6.5       6.5
 6 Sepal Length     5.4        5.7       7.6
 7 Sepal Length     4.6        6.3       4.9
 8 Sepal Length     5          4.9       7.3
 9 Sepal Length     4.4        6.6       6.7
10 Sepal Length     4.9        5.2       7.2
# ... with 190 more rows
1 голос
/ 29 марта 2020

Вот что я могу предложить для достижения первого результата:

df <- iris

# Changing column order
df <- df %>%
  select(5, 1:4)

Выбор столбцов вида, Лепесток, Длина, Sepal.Length и сбор:

length <- df %>% 
  select(1,2,4) %>%
  gather("Part", "Length", -1)

length$Part <- gsub(pattern = ".Length", replacement = "", length$Part, )

head(length)
  Species  Part Length
1  setosa Sepal    5.1
2  setosa Sepal    4.9
3  setosa Sepal    4.7
4  setosa Sepal    4.6
5  setosa Sepal    5.0
6  setosa Sepal    5.4

Выбор вида, Petal.Width, Sepal.Width столбцов и сбор:

width <- df %>% 
  select(1,3,5) %>%
  gather("Part", "Width", -1)

width$Part <- gsub(pattern = ".Width", replacement = "", width$Part, )

head(width)
  Species  Part Width
1  setosa Sepal   3.5
2  setosa Sepal   3.0
3  setosa Sepal   3.2
4  setosa Sepal   3.1
5  setosa Sepal   3.6
6  setosa Sepal   3.9

Комбинирование 2 наборов данных:

merged_df <- length %>%
  mutate(Width = width$Width)

head(merged_df)
  Species  Part Length Width
1  setosa Sepal    5.1   3.5
2  setosa Sepal    4.9   3.0
3  setosa Sepal    4.7   3.2
4  setosa Sepal    4.6   3.1
5  setosa Sepal    5.0   3.6
6  setosa Sepal    5.4   3.9
...