Skip to main content

tidyr HOW-TO

Шпаргалка возможностей пакета tidyr.

Общее

Пакет tidyr за авторством Hadley Wickham'а предназначен для первичной обработки сырых данных, в частности - изменения их структуры. Для начала нам потребуются сам tidyr, а также dplyr:

library(tidyr)
library(dplyr)

expand()

Назначение

Создает data.frame включающий все комбинации заданных переменных без перестановок

Использование

expand(data, ...)

Аргументы

  • data - оригинальный data.frame
  • ... - имена переменных для комбинации (допустимы выражения вместо непосредственно имен)

Примеры использования

Данные:

df <- data.frame(a = c(1, 2, 5), b = c(3, 5, 3), c = c(1, 2, 3))
df
##   a b c
## 1 1 3 1
## 2 2 5 2
## 3 5 3 3

Все комбинации переменных vs и cyl:

expand(mtcars, vs, cyl)
##   vs cyl
## 1  0   4
## 2  0   6
## 3  0   8
## 4  1   4
## 5  1   6
## 6  1   8

Все комбинации переменных cyl и mpg, последняя при этом принимает только минимальное или максимальное значение:

expand(mtcars, cyl, mpg = seq_range(mpg, 2))
##   cyl  mpg
## 1   4 10.4
## 2   4 33.9
## 3   6 10.4
## 4   6 33.9
## 5   8 10.4
## 6   8 33.9

Все комбинации переменных cyl и mpg, последняя при этом принимает значения из разбитого на 5 равных частей диапазона:

expand(mtcars, cyl, mpg = seq_range(mpg, 5))
##    cyl    mpg
## 1    4 10.400
## 2    4 16.275
## 3    4 22.150
## 4    4 28.025
## 5    4 33.900
## 6    6 10.400
## 7    6 16.275
## 8    6 22.150
## 9    6 28.025
## 10   6 33.900
## 11   8 10.400
## 12   8 16.275
## 13   8 22.150
## 14   8 28.025
## 15   8 33.900

Все комбинации переменных a, b и c:

expand(df)
##    a b c
## 1  1 3 1
## 2  1 3 2
## 3  1 3 3
## 4  1 5 1
## 5  1 5 2
## 6  1 5 3
## 7  2 3 1
## 8  2 3 2
## 9  2 3 3
## 10 2 5 1
## 11 2 5 2
## 12 2 5 3
## 13 5 3 1
## 14 5 3 2
## 15 5 3 3
## 16 5 5 1
## 17 5 5 2
## 18 5 5 3

Все комбинации переменных a и b:

expand(df, a, b)
##   a b
## 1 1 3
## 2 1 5
## 3 2 3
## 4 2 5
## 5 5 3
## 6 5 5

Все комбинации переменных a и c:

expand(df, a, c)
##   a c
## 1 1 1
## 2 1 2
## 3 1 3
## 4 2 1
## 5 2 2
## 6 2 3
## 7 5 1
## 8 5 2
## 9 5 3

Все комбинации переменных b и c:

expand(df, b, c)
##   b c
## 1 3 1
## 2 3 2
## 3 3 3
## 4 5 1
## 5 5 2
## 6 5 3

extract()

Назначение

Применяет регулярное выражение к переменной и создает одну или несколько новых на основе результата

Использование

extract(data, col, into, regex = "([[:alnum:]]+)", remove = TRUE,
        convert = FALSE, ...)

Аргументы

  • data - оригинальный data.frame
  • col - имя переменной
  • into - имена новых переменных
  • regex - регулярное выражение для поиска требуемых данных
  • remove - если TRUE - удаляет col из результирующего data.frame
  • convert - если TRUE - применяет type.convert c as.is = TRUE к новым переменным
  • ... - дополнительные аргументы для regexec

Примеры использования

Данные:

df <- data.frame(x = c("a.b", "a.d", "b.c"))
df
##     x
## 1 a.b
## 2 a.d
## 3 b.c

Извлечь из переменной x первую букву:

df %>% extract(x, "A")
##   A
## 1 a
## 2 a
## 3 b

Разбить переменную x:

df %>% extract(x, c("A", "B"), "([[:alnum:]]+)\\.([[:alnum:]]+)")
##   A B
## 1 a b
## 2 a d
## 3 b c

extract_numeric()

Назначение

Используя регулярное выражение удаляет все нецифровые знаки из строки и трансформирует результат в число

Использование

extract_numeric(x)

Аргументы

  • x - character vector или factor

Примеры использования

extract_numeric("$1,200.34")
## [1] 1200.34
extract_numeric("-2%")
## [1] -2

Может некорректно работать со строками, которые точно не являются цифровыми данными:

extract_numeric("-2-2")
## Warning in extract_numeric("-2-2"): NAs introduced by coercion
## [1] NA
extract_numeric("12abc34")
## [1] 1234

gather()

Назначение

Объединяет переменные, имена переменных для объединения становятся уровнями переменной key, значения объединенных переменных заполняют соответственно переменную value

Использование

gather(data, key, value, ..., na.rm = FALSE, convert = FALSE)

Аргументы

  • data - оригинальный data.frame
  • key, value - key, value переменные
  • ... - переменные для объединения, выбор нескольких: x:z, исключить: -y
  • na.rm - если TRUE - удалить все NA
  • convert - если TRUE - применяет type.convert к key переменной

Примеры использования

Данные:

stocks <- data.frame(
time = as.Date('2009-01-01') + 0:9,
X = rnorm(10, 0, 1),
Y = rnorm(10, 0, 2),
Z = rnorm(10, 0, 4)
)
stocks
##          time          X          Y           Z
## 1  2009-01-01  0.7722318 -0.3642657 -2.50084998
## 2  2009-01-02 -1.1323590  0.7835050 -1.44378404
## 3  2009-01-03 -0.8616668 -2.5209075  2.19735867
## 4  2009-01-04 -0.6363773 -3.6459329 -2.27906230
## 5  2009-01-05  1.3777546  0.6740792  2.47886088
## 6  2009-01-06  1.1138555 -2.7431003  2.13743541
## 7  2009-01-07 -0.4055423 -0.3971725  0.32445108
## 8  2009-01-08 -0.6551642 -1.3071296 -4.39142177
## 9  2009-01-09 -0.8421454 -0.9334135 -0.02401832
## 10 2009-01-10 -0.1655489 -0.6961085 -0.82861047

Объединить имена переменных X, Y, Z в качестве уровней новой переменной stock, значения объединенных переменных заполнят переменную price:

stocks %>% gather(stock, price, -time)
##          time stock       price
## 1  2009-01-01     X  0.77223178
## 2  2009-01-02     X -1.13235898
## 3  2009-01-03     X -0.86166677
## 4  2009-01-04     X -0.63637728
## 5  2009-01-05     X  1.37775462
## 6  2009-01-06     X  1.11385552
## 7  2009-01-07     X -0.40554232
## 8  2009-01-08     X -0.65516418
## 9  2009-01-09     X -0.84214541
## 10 2009-01-10     X -0.16554890
## 11 2009-01-01     Y -0.36426573
## 12 2009-01-02     Y  0.78350495
## 13 2009-01-03     Y -2.52090748
## 14 2009-01-04     Y -3.64593285
## 15 2009-01-05     Y  0.67407924
## 16 2009-01-06     Y -2.74310035
## 17 2009-01-07     Y -0.39717249
## 18 2009-01-08     Y -1.30712963
## 19 2009-01-09     Y -0.93341350
## 20 2009-01-10     Y -0.69610847
## 21 2009-01-01     Z -2.50084998
## 22 2009-01-02     Z -1.44378404
## 23 2009-01-03     Z  2.19735867
## 24 2009-01-04     Z -2.27906230
## 25 2009-01-05     Z  2.47886088
## 26 2009-01-06     Z  2.13743541
## 27 2009-01-07     Z  0.32445108
## 28 2009-01-08     Z -4.39142177
## 29 2009-01-09     Z -0.02401832
## 30 2009-01-10     Z -0.82861047

separate()

Назначение

Разбивает переменную на несколько

Использование

separate(data, col, into, sep = "[^[:alnum:]]+", remove = TRUE,
         convert = FALSE, extra = "error", ...)

Аргументы

  • data - оригинальный data.frame
  • col - имя переменной для разбивки
  • into - имена новых переменных
  • sep - разделитель, если character - воспринимается как регулярное выражение, по-умолчанию - последовательность не цифро-буквенных знаков, если numeric - воспринимается как позиция для разделения
  • remove - если TRUE - удаляет col из результирующего data.frame
  • convert - если TRUE - применяет type.convert c as.is = TRUE к новым переменным
  • extra - если sep - character, то аргумент задает реакцию на превышение допустимого числа новых переменных (into):
    • error - ошибка по-умолчанию
    • drop - возвращает length(into), отбрасывает все сверху или расширяет data.frame
    • merge - разделяет только length(into) раз
  • ... - дополнительные переменные для strsplit

Примеры использования

Данные:

df <- data.frame(x = c("a.b", "a.d", "b.c"))
df
##     x
## 1 a.b
## 2 a.d
## 3 b.c

Разбить переменную x на две, разделитель - .:

df %>% separate(x, c("A", "B"))
##   A B
## 1 a b
## 2 a d
## 3 b c

Если строки нельзя разделить на равное число переменных:

df <- data.frame(x = c("a", "a b", "a b c"))
df %>% separate(x, c("a", "b"), extra = "merge")
##   a    b
## 1 a <NA>
## 2 a    b
## 3 a  b c
df %>% separate(x, c("a", "b"), extra = "drop")
##   a    b
## 1 a <NA>
## 2 a    b
## 3 a    b

Данные:

df <- data.frame(x = c("x: 123", "y: error: 7"))
df
##             x
## 1      x: 123
## 2 y: error: 7

Разбить строки строго на две переменные по первому включению sep:

df %>% separate(x, c("key", "value"), ": ", extra = "merge")
##   key    value
## 1   x      123
## 2   y error: 7

seq_range()

Назначение

Возвращает вектор из n значений x от минимального до максимального с равными промежутками

Использование

seq_range(x, n)

Аргументы

  • x - numeric vector
  • n - число значений

Примеры использования

Разобьем диапазон значений вектора 1:100:

seq_range(1:100, 5)
## [1]   1.00  25.75  50.50  75.25 100.00

spread()

Назначение

Переформатирует data.frame - используя в качестве имен новых переменных уровни заданной переменной key, а в качестве значений - соответствующие значения переменной value.

Использование

spread(data, key, value, fill = NA, convert = FALSE, drop = TRUE)

Аргументы

  • data - numeric vector
  • key - переменная, чьи уровни станут новыми переменными
  • value - переменная, соответствующими значениями которой будут заполнены новые столбцы
  • fill - если для комбинации переменной key и других переменных нет значения - подставляет на его место указанное
  • convert - если TRUE - применяет type.convert c as.is = TRUE к новым переменным
  • drop - если FALSE - сохранить уровни факторов, для которых нет значений в данных, заполняя их по правилу fill

Примеры использования

Данные:

stocks <- data.frame(
time = as.Date('2009-01-01') + 0:9,
X = rnorm(10, 0, 1),
Y = rnorm(10, 0, 2),
Z = rnorm(10, 0, 4)
)
stocks
##          time          X          Y          Z
## 1  2009-01-01  0.3911387  2.0635862 -6.3953715
## 2  2009-01-02  0.1203100 -1.3411346 -4.5907582
## 3  2009-01-03 -0.3916139 -0.3763128 -0.6275635
## 4  2009-01-04 -0.2890859  1.0035137 -2.9846424
## 5  2009-01-05  0.2296824  1.0974012  0.6136485
## 6  2009-01-06  0.0278537  4.9167183 -5.7563632
## 7  2009-01-07  0.7349981  0.4856101 -6.7558963
## 8  2009-01-08 -0.5096926 -0.8247462  2.5661235
## 9  2009-01-09  0.2338707 -0.5513422 -0.6923370
## 10 2009-01-10  2.3231925  0.2870178  1.7580478

Противоположность gather:

stocksm <- stocks %>% gather(stock, price, -time)
head(stocksm)
##         time stock      price
## 1 2009-01-01     X  0.3911387
## 2 2009-01-02     X  0.1203100
## 3 2009-01-03     X -0.3916139
## 4 2009-01-04     X -0.2890859
## 5 2009-01-05     X  0.2296824
## 6 2009-01-06     X  0.0278537
stocksm %>% spread(stock, price)
##          time          X          Y          Z
## 1  2009-01-01  0.3911387  2.0635862 -6.3953715
## 2  2009-01-02  0.1203100 -1.3411346 -4.5907582
## 3  2009-01-03 -0.3916139 -0.3763128 -0.6275635
## 4  2009-01-04 -0.2890859  1.0035137 -2.9846424
## 5  2009-01-05  0.2296824  1.0974012  0.6136485
## 6  2009-01-06  0.0278537  4.9167183 -5.7563632
## 7  2009-01-07  0.7349981  0.4856101 -6.7558963
## 8  2009-01-08 -0.5096926 -0.8247462  2.5661235
## 9  2009-01-09  0.2338707 -0.5513422 -0.6923370
## 10 2009-01-10  2.3231925  0.2870178  1.7580478

Разбить price по переменной time:

stocksm %>% spread(time, price)
##   stock 2009-01-01 2009-01-02 2009-01-03 2009-01-04 2009-01-05 2009-01-06
## 1     X  0.3911387   0.120310 -0.3916139 -0.2890859  0.2296824  0.0278537
## 2     Y  2.0635862  -1.341135 -0.3763128  1.0035137  1.0974012  4.9167183
## 3     Z -6.3953715  -4.590758 -0.6275635 -2.9846424  0.6136485 -5.7563632
##   2009-01-07 2009-01-08 2009-01-09 2009-01-10
## 1  0.7349981 -0.5096926  0.2338707  2.3231925
## 2  0.4856101 -0.8247462 -0.5513422  0.2870178
## 3 -6.7558963  2.5661235 -0.6923370  1.7580478

unite()

Назначение

Объединяет переменные в одну

Использование

unite(data, col, ..., sep = "_", remove = TRUE)

Аргументы

  • data - numeric vector
  • col - имя базовой переменной
  • ... - переменные для объединения с базовой
  • sep - разделитель между значениями объединенных переменных
  • remove - если TRUE - удаляет переменные для объединения

Примеры использования

Объединяем переменные vs и am в одну:

mtcars %>%
  unite_("vs_am", c("vs", "am")) %>%
  head()
##                    mpg cyl disp  hp drat    wt  qsec vs_am gear carb
## Mazda RX4         21.0   6  160 110 3.90 2.620 16.46   0_1    4    4
## Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02   0_1    4    4
## Datsun 710        22.8   4  108  93 3.85 2.320 18.61   1_1    4    1
## Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44   1_0    3    1
## Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02   0_0    3    2
## Valiant           18.1   6  225 105 2.76 3.460 20.22   1_0    3    1

Противоположность separate:

mtcars %>%
  unite(vs_am, vs, am) %>%
  separate(vs_am, c("vs", "am")) %>%
  head()
##                    mpg cyl disp  hp drat    wt  qsec vs am gear carb
## Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
## Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
## Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
## Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
## Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
## Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1

unnest()

Назначение

Разбивает переменную на большее число строк за счет раскрытия вложенных элементов

Использование

unnest(data, col = NULL)

Аргументы

  • data - оригинальный data.frame
  • col - переменная, которую нужно разбить на большее число строк

Примеры использования

Данные:

df <- data.frame(
x = 1:3,
y = c("a", "d,e,f", "g,h"),
stringsAsFactors = FALSE
)
df
##   x     y
## 1 1     a
## 2 2 d,e,f
## 3 3   g,h

Разбить переменную y на большее число строк:

df %>%
  transform(y = strsplit(y, ",")) %>%
  unnest(y)
##   x y
## 1 1 a
## 2 2 d
## 3 2 e
## 4 2 f
## 5 3 g
## 6 3 h

Разобьем стандартный набор данных iris по виду цветка:

my_list <- lapply(split(subset(iris, select = -Species),iris$Species),
                  "[", 1:2, )
my_list
## $setosa
##   Sepal.Length Sepal.Width Petal.Length Petal.Width
## 1          5.1         3.5          1.4         0.2
## 2          4.9         3.0          1.4         0.2
##
## $versicolor
##    Sepal.Length Sepal.Width Petal.Length Petal.Width
## 51          7.0         3.2          4.7         1.4
## 52          6.4         3.2          4.5         1.5
##
## $virginica
##     Sepal.Length Sepal.Width Petal.Length Petal.Width
## 101          6.3         3.3          6.0         2.5
## 102          5.8         2.7          5.1         1.9

Соберем список обратно в data.frame:

unnest(my_list)
## Source: local data frame [6 x 4]
##
##   Sepal.Length Sepal.Width Petal.Length Petal.Width
## 1          5.1         3.5          1.4         0.2
## 2          4.9         3.0          1.4         0.2
## 3          7.0         3.2          4.7         1.4
## 4          6.4         3.2          4.5         1.5
## 5          6.3         3.3          6.0         2.5
## 6          5.8         2.7          5.1         1.9

Добавим потерявшуюся переменную Species:

unnest(my_list, Species)
##      Species Sepal.Length Sepal.Width Petal.Length Petal.Width
## 1     setosa          5.1         3.5          1.4         0.2
## 2     setosa          4.9         3.0          1.4         0.2
## 3 versicolor          7.0         3.2          4.7         1.4
## 4 versicolor          6.4         3.2          4.5         1.5
## 5  virginica          6.3         3.3          6.0         2.5
## 6  virginica          5.8         2.7          5.1         1.9