Импорт из текста

При помощи функций read.table(), read.csv(), read.csv2(), read.delim() загружают данные из файла во фрейм данных. Эти функции довольно похожи, только у них разные значения формальных параметров по умолчанию.

Например:

read.csv(sep=',', dec=".") – значения разделены запятыми, дробная часть отделяется точкой

read.csv2(sep=';', dec=",") – значения разделены запятыми, дробная часть отделяется точкой, как принято в России

В реальной жизни мы используем эти функции с параметром file="имя текстового файла с данными"

в наших примерах нагляднее будет в этих функциях вместо параметра file= воспользоваться параметром text=

  girls.textdata= 
  "row.name|name|age|hobby|height
  g1|Лена|19|лыжи|166
  g2|Жанна|22|вышивка|156,5
  g3|Даша|29|лыжи|180
  g4|Ира|26|танцы|170 
  g5|Зина|16|танцы|160" 
girls <- read.delim(header=T,
  sep="|" , dec = ",",
  text= girls.textdata,
  row.names = 1, 
  stringsAsFactors = F
  )

Обьяснения параметров:

Результат импорта:

str(girls)
## 'data.frame':    5 obs. of  4 variables:
##  $ name  : chr  "Лена" "Жанна" "Даша" "Ира" ...
##  $ age   : int  19 22 29 26 16
##  $ hobby : chr  "лыжи" "вышивка" "лыжи" "танцы" ...
##  $ height: num  166 156 180 170 160
girls
##       name age   hobby height
##   g1  Лена  19    лыжи  166.0
##   g2 Жанна  22 вышивка  156.5
##   g3  Даша  29    лыжи  180.0
##   g4   Ира  26   танцы  170.0
##   g5  Зина  16   танцы  160.0

В следующем примере вместо возраста указана дата рождения и имена строк генерируются автоматически вместо чтения их из текстовых данных. Применен параметр colClasses=

  girls.textdata2= 
  "name|birth.date|hobby|height
  Лена|1995-02-12|лыжи|166
  Жанна|1988-2-20|вышивка|156,5
  Даша|1990-12-04|лыжи|180
  Ира|2000-11-11|танцы|170" 
girls2 <- read.delim(header=T,
           colClasses = c("character","Date","NULL", NA),
           sep="|" , dec=",",
  text= girls.textdata2,
  row.names = NULL
  )

Обьяснения параметров:

Результаты:

str(girls2)
## 'data.frame':    4 obs. of  3 variables:
##  $ name      : chr  "  Лена" "  Жанна" "  Даша" "  Ира"
##  $ birth.date: Date, format: "1995-02-12" "1988-02-20" ...
##  $ height    : num  166 156 180 170
girls2
##      name birth.date height
## 1    Лена 1995-02-12  166.0
## 2   Жанна 1988-02-20  156.5
## 3    Даша 1990-12-04  180.0
## 4     Ира 2000-11-11  170.0

Импортируем также и данные про мальчиков

boys.textdata= 
  "row.name|name|age|hobby|height
  b1|Гена|19|лыжи|188
  b2|Женя|32|мотоцикл|166,5
  b3|Саша|29|лыжи|180
  b4|Дима|26|танцы|170" 
boys <- read.delim(header=T,
  sep="|" , dec = ",",
  text= boys.textdata,
  row.names = 1, 
  stringsAsFactors = F
  )
boys
##      name age    hobby height
##   b1 Гена  19     лыжи  188.0
##   b2 Женя  32 мотоцикл  166.5
##   b3 Саша  29     лыжи  180.0
##   b4 Дима  26    танцы  170.0

Работа с файлами и папками

Узнаем, какая у нас текущая рабочая директория

getwd()  
## [1] "/Users/ikochergin/Documents/bivni_msu"

Если папка не сущетсвует, создаем. Если бы первая функция вернула TRUE, то операция || (или) не вызвала бы вторую функцию.

dir.exists("data") || dir.create("data") 
## [1] TRUE

Скачиваем файл из интернета и раззиповываем

url_world_data <- "http://crow.academy.ru/~ikocherg/stud_do/2015vesna/world.txt.zip"
download.file(url_world_data,destfile = "data/world.txt.zip")
unzip("data/world.txt.zip",exdir = "data")

Мы еще не проходили еще продвинутые шаблоны строк регулярные выражения, которые сейчас поддерживают практически все языки программирования. Следующий код ищет файлы, соответствующие шаблону (pattern) в текущей папке и еще поддиректориях (рекурсивно: recursive=T). В шаблоне указано, что в начале (^) названия должно быть слово city либо country, затем любые символы в любом количестве (.*) потом в конце ($) названия txt.

list.files(pattern = "^(city|country).*txt$",path=".", recursive = T,include.dirs = T)
## [1] "data/city.txt"                     
## [2] "data/country.txt"                  
## [3] "data/countrylanguage.txt"          
## [4] "src/world.data/city.txt"           
## [5] "src/world.data/country.txt"        
## [6] "src/world.data/countrylanguage.txt"

Импорт данных из тектовых файлов

Функции head() и tail() позволяют посмотреть начало и конец векторов и фреймов данных. по умолчанию показывают 6 строк

head(cars)
##   speed dist
## 1     4    2
## 2     4   10
## 3     7    4
## 4     7   22
## 5     8   16
## 6     9   10
tail(cars)
##    speed dist
## 45    23   54
## 46    24   70
## 47    24   92
## 48    24   93
## 49    24  120
## 50    25   85

Функция readLines() позволяет читать текстовый файл как масив текстовых строк (не разбирая на поля)

city.text <- readLines("data/city.txt")
head(city.text)
## [1] "CityID;Name;CountryCode;District;Population"
## [2] "1;Kabul;AFG;Kabol;1780000"                  
## [3] "2;Qandahar;AFG;Qandahar;237500"             
## [4] "3;Herat;AFG;Herat;186800"                   
## [5] "4;Mazar-e-Sharif;AFG;Balkh;127800"          
## [6] "5;Amsterdam;NLD;Noord-Holland;731200"
city <- read.csv2("data/city.txt",as.is=T)
str(city)
## 'data.frame':    4079 obs. of  5 variables:
##  $ CityID     : int  1 2 3 4 5 6 7 8 9 10 ...
##  $ Name       : chr  "Kabul" "Qandahar" "Herat" "Mazar-e-Sharif" ...
##  $ CountryCode: chr  "AFG" "AFG" "AFG" "AFG" ...
##  $ District   : chr  "Kabol" "Qandahar" "Herat" "Balkh" ...
##  $ Population : int  1780000 237500 186800 127800 731200 593321 440900 234323 201843 193238 ...
country <- read.csv2("data/country.txt",as.is=T)
str(country)
## 'data.frame':    239 obs. of  15 variables:
##  $ CountryCode   : chr  "ABW" "AFG" "AGO" "AIA" ...
##  $ Name          : chr  "Aruba" "Afghanistan" "Angola" "Anguilla" ...
##  $ Continent     : chr  "North America" "Asia" "Africa" "North America" ...
##  $ Region        : chr  "Caribbean" "Southern and Central Asia" "Central Africa" "Caribbean" ...
##  $ SurfaceArea   : num  193 652090 1246700 96 28748 ...
##  $ IndepYear     : int  NA 1919 1975 NA 1912 1278 NA 1971 1816 1991 ...
##  $ Population    : int  103000 22720000 12878000 8000 3401200 78000 217000 2441000 37032000 3520000 ...
##  $ LifeExpectancy: num  78.4 45.9 38.3 76.1 71.6 83.5 74.7 74.1 75.1 66.4 ...
##  $ GNP           : num  828 5976 6648 63.2 3205 ...
##  $ GNPOld        : num  793 NA 7984 NA 2500 ...
##  $ LocalName     : chr  "Aruba" "Afganistan/Afqanestan" "Angola" "Anguilla" ...
##  $ GovernmentForm: chr  "Nonmetropolitan Territory of The Netherlands" "Islamic Emirate" "Republic" "Dependent Territory of the UK" ...
##  $ HeadOfState   : chr  "Beatrix" "Mohammad Omar" "Josй Eduardo dos Santos" "Elisabeth II" ...
##  $ Capital       : int  129 1 56 62 34 55 33 65 69 126 ...
##  $ Code2         : chr  "AW" "AF" "AO" "AI" ...

Пакет dplyr

Этот пакет позволяет делать с фреймами данных операции аналогичные по возможностям операм языка SQL, кроме того у этого пакета есть возможности интеграции с базами данных.

Шпаргалка по пакету находится в разделе шпаргалок RStudio под именем Data Wrangling Cheat Sheet

library(dplyr)

При загрузке этого пакета загружается оператор %>% “pipe”, позволяющй устраивать конвеер преобразований. Допустим выражение h(g(f(x,p),q),r) выглядит громозко. Можно воспользоваться оператором pipe, подставляющий функции справа от него, в качестве первого параметра результат выражения, находящегося слева от него. Мы может для h(g(f(x,p),q),r) написать эквивалентное выражение x %>% f(p) %>% g(q) %>% h(r). Заметьте, то первый параметр функций не пишется явно.

Некоторые функции пакета

  • arrange(df,поле) или arrange(df,desc(поле)) – упорядочить (выдать упорядоченным) фрейм данных в порядке возрастания или убывания указанного поля.
  • select(df,какие столбцы выдавать) выдаст из df только указанные столбцы.
  • filter(df,условия отбора) – выбрать строки, удовлетворяющие условию
  • group_by(df,список полей по которым нужно группировать) – разбить фрейм данных на группы.
  • summarize(df,новое.поле=групповая_функция(поле)) – при помощи групповой функции подсчитать по всему фрейма данных или по каждой группе итоговый показатель при помощи групповых функций (mean,median,min,max,sd,sum,var)

Примеры использования этих функций

Выберем нужные столбцы:

 select(girls,-c(age))
##       name   hobby height
##   g1  Лена    лыжи  166.0
##   g2 Жанна вышивка  156.5
##   g3  Даша    лыжи  180.0
##   g4   Ира   танцы  170.0
##   g5  Зина   танцы  160.0
 select(girls,name, contains("hei"))
##       name height
##   g1  Лена  166.0
##   g2 Жанна  156.5
##   g3  Даша  180.0
##   g4   Ира  170.0
##   g5  Зина  160.0

Найдем медиану высот девушек, а затем найдем девушку, чья высота равна медиане

 ( df1 <- summarize(girls,median.height=median(height))  )
##   median.height
## 1           166
   filter(girls,df1$median.height==height)
##   name age hobby height
## 1 Лена  19  лыжи    166

Разобьем таблицу (data frame) девушек на группы по хобби, и выдадим сколько девушек в группе и их средний возраст.

girls %>% 
  group_by(hobby) %>% 
  summarize(mean.age=mean(age),count=n())  
## Source: local data frame [3 x 3]
## 
##     hobby mean.age count
##     (chr)    (dbl) (int)
## 1 вышивка       22     1
## 2    лыжи       24     2
## 3   танцы       21     2

Добавим сортировку по убыванию среднего возраста

girls %>% 
  group_by(hobby) %>% 
  summarize(mean.age=mean(age),count=n())  %>% 
  arrange(desc(mean.age))
## Source: local data frame [3 x 3]
## 
##     hobby mean.age count
##     (chr)    (dbl) (int)
## 1    лыжи       24     2
## 2 вышивка       22     1
## 3   танцы       21     2

Соединение таблиц

Например, бабушки на лавочки у подъезда хотят обсудить возможные пары девочек и мальчиков из их подъезда. Они решили рассмотреть пары с общими хобби

girls
##       name age   hobby height
##   g1  Лена  19    лыжи  166.0
##   g2 Жанна  22 вышивка  156.5
##   g3  Даша  29    лыжи  180.0
##   g4   Ира  26   танцы  170.0
##   g5  Зина  16   танцы  160.0
boys
##      name age    hobby height
##   b1 Гена  19     лыжи  188.0
##   b2 Женя  32 мотоцикл  166.5
##   b3 Саша  29     лыжи  180.0
##   b4 Дима  26    танцы  170.0
inner_join(x = girls,y=boys,by=c("hobby"))
##   name.x age.x hobby height.x name.y age.y height.y
## 1   Лена    19  лыжи      166   Гена    19      188
## 2   Лена    19  лыжи      166   Саша    29      180
## 3   Даша    29  лыжи      180   Гена    19      188
## 4   Даша    29  лыжи      180   Саша    29      180
## 5    Ира    26 танцы      170   Дима    26      170
## 6   Зина    16 танцы      160   Дима    26      170

Заметьте, что человек, у кого с его хобби нет пары не попадает в результат внутреннего соединения. О других типах соединения будет рассказано позже.