source file: http://1drv.ms/1GpekJi
Если исходный файл показывается с крокозяброй вместо русского текста, нужно сменить кодировку c cp1251(Windows) на UTF-8(Unicode) в RStudio.
If Russian text seems to be srambled in source file, please, change encoding from cp1251(Windows) to UTF-8(Unicode) in RStudio.
1. menu Tools -> Global option / General / Default text encoding (UTF-8)
2. close source file (this file) and than reopen it.
Зададим таблицы данны (dataframe) для простых примеров соединения таблиц. Представьте себе: на скамейке перед подъездом сидят бабушки. Они хотят обсудить, какие мальчики и девочки могли бы составить пары. Они открыли ноутбук, запустили RStudio и … После подключения пакета dplyr мы создадим 2 таблицы mal (мальчики) и dev (девочки).
library(dplyr)
##
## Attaching package: 'dplyr'
##
## The following object is masked from 'package:stats':
##
## filter
##
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
mal <- data_frame(mal.name="Ваня", mal.age=40, mal.hobby = "велосипед")
# базовая функция rbind (bind by row) соединяет 2 таблицы ставя строки второй сразу после строк первой
# базовая функция cbind (bind by column) соединяет 2 таблицы ставя столбцы второй сразу после столбцов первой
row <- data_frame(mal.name="Миша", mal.age=19, mal.hobby = "лыжи")
mal <- rbind( mal,row) # добавим вторую строку
mal
## Source: local data frame [2 x 3]
##
## mal.name mal.age mal.hobby
## 1 Ваня 40 велосипед
## 2 Миша 19 лыжи
И еще 2 строки другим способом
mal[3,] <- data_frame("Дима", 35, "велосипед")
mal[4,] <- data_frame("Гаврила",29, "мотоцикл")
и еще одну строку
row <- data_frame(mal.name="Юра", mal.age=44, mal.hobby = "лыжи")
mal <- rbind( mal,row) # добавим вторую строку
mal
## Source: local data frame [5 x 3]
##
## mal.name mal.age mal.hobby
## 1 Ваня 40 велосипед
## 2 Миша 19 лыжи
## 3 Дима 35 велосипед
## 4 Гаврила 29 мотоцикл
## 5 Юра 44 лыжи
Замечание 1 в отличие от языка SQL, в языке R точка – это обычный символ в имени, а не разделитель между именем таблицы и столбца. Мы тут используем такие приставки dev.
и mal.
чтобы имена столбцов были уникальными в 2 соединямемых таблицах.
Замечание 2 на семинаре мы пользовались командами
mal <- data.frame()
fix(mal)
и в визуальном редакторе таблиц определяли имена столбцов и их типы и вводили значения ячеек. С точки зрения воспроизводимости примеров такой способ не годится.
Теперь вводим таблицу девочек
dev <- data_frame(dev.name="Оля", dev.age=28, dev.hobby="лыжи")
dev[2,] <- data_frame("Зина", 19, "вышивание")
dev[3,] <- list("Лена" , 19, "велосипед")
row <- data_frame(dev.name="Ира", dev.age=31, dev.hobby="лыжи")
dev<- rbind(dev,row)
dev
## Source: local data frame [4 x 3]
##
## dev.name dev.age dev.hobby
## 1 Оля 28 лыжи
## 2 Зина 19 вышивание
## 3 Лена 19 велосипед
## 4 Ира 31 лыжи
Операция join – это одна из фундаментальных операций современных баз данных. Соединяя при пгомощи этой оперрации таблицы, мы получаем в качестве результата операции join таблицу в которой часть столбцов взята из первой таблицы, а часть стобцов из второй таблицы
Строки результата образуют не комбинации произвольных строк левой и правой таблицы, а только строк соответствующих друг другу. Как определяется это соответствие? Обычно накладывается условие равенства друг другу значений некоторых полей в соединяемых таблицах.
Например, бабушки у подъезда хотят рассмотреть в первую очередь те потенциальные пары, которые объединяют общие интересы ( mal.hobby == dev.hobby) Для этого подходит операция inner_join(левая_таблица, правая_таблица, by = условие_соединения)
inner_join(dev, mal,by=c("dev.hobby"="mal.hobby"))
## Source: local data frame [6 x 5]
##
## dev.name dev.age dev.hobby mal.name mal.age
## 1 Оля 28 лыжи Миша 19
## 2 Оля 28 лыжи Юра 44
## 3 Лена 19 велосипед Ваня 40
## 4 Лена 19 велосипед Дима 35
## 5 Ира 31 лыжи Миша 19
## 6 Ира 31 лыжи Юра 44
Вы видите в результате несколько раз посторяются строки из таблицы девочки и таблицы мальчики, у которых хобби позволяет им быть участниками нескольких потенциальных пар. С другой стороны, мальчик Гаврила и девочка Зина имеют более редкие увлечения и они совсем не упомянуты в результате, потому что операция inner_join исключает строки, которым нет соответсвия в другой табице из результата.
Результат соединения можно использовать далее как обычную таблицу (data frame) и применять к ним обычные операции filter(), arrange(),select(), summarise() и т.п.
Например бабушки захотели посмотреть пары, где возраст не отличается более чем на 15 лет и результат для них нужно упорядочить по имени девочки:
inner_join(dev, mal,by=c("dev.hobby"="mal.hobby")) %>%
filter(abs(mal.age-dev.age)<=15) %>%
arrange(dev.name)
## Source: local data frame [3 x 5]
##
## dev.name dev.age dev.hobby mal.name mal.age
## 1 Ира 31 лыжи Миша 19
## 2 Ира 31 лыжи Юра 44
## 3 Оля 28 лыжи Миша 19
Иногда требуется включать строки из одной из таблиц в результат, даже если им нет соответсвия в другой таблице. Тогда используютс операции left_join(), right_join() и full_join(). Такие соединения назвают внешними
Если мы хотим левую таблицу сделать более приоритетной, то есть включать ее строки в результат, даже если для них нет соответствия в правой таблице, то мы используем операцию left_join()
left_join(dev, mal,by=c("dev.hobby"="mal.hobby"))
## Source: local data frame [7 x 5]
##
## dev.name dev.age dev.hobby mal.name mal.age
## 1 Оля 28 лыжи Миша 19
## 2 Оля 28 лыжи Юра 44
## 3 Зина 19 вышивание NA NA
## 4 Лена 19 велосипед Ваня 40
## 5 Лена 19 велосипед Дима 35
## 6 Ира 31 лыжи Миша 19
## 7 Ира 31 лыжи Юра 44
Зина появилась в списке, а дефицит мальчиков с таким же хобби вышивание был “восполнен” “пустым мальчиком” то есть в этой строке все поля из таблицы mal заполненны пустыми значениями NA
В правом внешнем соединении появляется Гаврила на мотоцикле с “пустой девочкой”.
right_join(dev, mal,by=c("dev.hobby"="mal.hobby"))
## Source: local data frame [7 x 5]
##
## dev.name dev.age dev.hobby mal.name mal.age
## 1 Лена 19 велосипед Ваня 40
## 2 Оля 28 лыжи Миша 19
## 3 Ира 31 лыжи Миша 19
## 4 Лена 19 велосипед Дима 35
## 5 NA NA мотоцикл Гаврила 29
## 6 Оля 28 лыжи Юра 44
## 7 Ира 31 лыжи Юра 44
В полном внешнем соединении есть и Гаврила на мотоцикле с “пустой девочкой” и вышивающая Зина с “пустым мальчиком”.
full_join(dev, mal,by=c("dev.hobby"="mal.hobby"))
## Source: local data frame [8 x 5]
##
## dev.name dev.age dev.hobby mal.name mal.age
## 1 Оля 28 лыжи Миша 19
## 2 Оля 28 лыжи Юра 44
## 3 Зина 19 вышивание NA NA
## 4 Лена 19 велосипед Ваня 40
## 5 Лена 19 велосипед Дима 35
## 6 Ира 31 лыжи Миша 19
## 7 Ира 31 лыжи Юра 44
## 8 NA NA мотоцикл Гаврила 29
Операции semi_join() и anti_join() в результат помешают строки только первой таблицы, а вторую таблицу используют для отбора строк первой.
Операция semi_join() выдаёт строки левой таблицы, для которых есть соответствующие строки в правой.
semi_join(dev, mal,by=c("dev.hobby"="mal.hobby"))
## Source: local data frame [3 x 3]
##
## dev.name dev.age dev.hobby
## 1 Лена 19 велосипед
## 2 Оля 28 лыжи
## 3 Ира 31 лыжи
А операция anti_join() – наоборот, выдаёт строки левой таблицы, для которых нет соответствующих строк в правой.
anti_join(dev, mal,by=c("dev.hobby"="mal.hobby"))
## Source: local data frame [1 x 3]
##
## dev.name dev.age dev.hobby
## 1 Зина 19 вышивание