A. Из файла:
* Comma separated values (.csv), tab separated values - самый частый случай
* Неструктуриированный текст - readLines, scan
* XML, HTML - library(XML), library(httr)
* JSON, YAML - library(rjson), library(RJSONIO)
* Excel - library(XLConnect), library(readxl)
* SAS, Stats, SPSS, MATLAB - library(foreign), library(sas7bdat)
Т.е. для разного типа данных чаще всего есть свои пакеты для их импорта.
B. Web - library(rvest)
- доступ к API
C. Базы данных:
* Реляционные - library(BBI), library(rmongodb)
* Нереляционные - library(rmongodb)
Это не исчерпывающий список
Основной иснтурмент - read.table:
* file - имя файла
* header - наличие или отсутствие заголовка в первой строке
* sep - разделитель значений
* quote - символы, обозначающие кавычки (для строкового типа)
* na.strings - строки, кодирующие пропущенные значения
* colClasses - типы столбцов (для быстродействия и указания типа): строка-фактор-дата/время) - если colClasses не указан, то R попытается угадать типы данных, н оне всегда верно * comment.char - символ, обозначаюащий комментарий
* skip - количество строк, пропускаемых с начала файла (если, например, заняты дополнительной ненужной табуляцией)
Функция read.csv, read.csv2, read.delim, read.delim2 - оболочки над read.table с различными вводными по умолчанию для аргументов, перечисленных выше
Шаги:
1. Импторт в дата фрейм (рассмотрен выше) 2. Очистка значений, проверка типов: проверяем корректность распознавания типов, корректируем при необходимости
3. Работа со строками: имена, переменные строкового типа, факторы: проверяем, чтобы перменные строкового типа и факторы не смешивались
4. Пропущенные значения: идентификация, способ обработки
5. Манипулирование переменными: преобразование, создание, удаление (например, создание новых из уже имещихся и т.д.)
6. Подсчет описательных статистик: split-apply-combine (чтобы посмотреть средние, в целом взглянуть на данные + ловим ошибки, связанные с недочищенными данными на предыдущих этапах) 7. Визуализация данных (делаем, например, ряд скатерр-плотов и убеждаемся, что нет никаких аномалий)
Типы переменных, на которых легко ошибиться при импорте: * Числовые типы становятся строковыми
** из-за пропущенных значений, отмеченных не как NA
Чтобы избежать нужно задать отметку пропущенных значений, это в том числе может быть вектор значений
#na.strings = c("NA", "Not available", "Missing")
Было 21 предупреждение (введите warnings() чтобы его просмотреть)
** из-за неверно указанных разделителя, десятичного знака
#sep = ",", dec = "."
N.B!В руссокой традиции часто вместо десятичной точки используется запятая, которая в .csv обычно определяет разделитель значений - отсюда проблемы
** из-за кавычек, сопроводительного текста или комментариев
#quote, comment.char, skip
#as.character, as.factor
#as.POSIXct
#as.POSIXlt
#as.Date
Вряд ли будем смотреть весь массив данных, стоит прогнать через ряд функций: str, summary, head, tail
#df[complete.cases(df), ]
# или
#na.omit(df)
help()
#df$new_var <- <...>
#df$old_var <- f(df$old_var)
#df$old_var <- NULL
Допустим, завершили предобработку данных и хотим записать файл с очищенными данными
* write.table, write.csv и write.csv2 - почти идентичные функции импоорта
* Если массив данных достаточно большой, то лучше всего отделять этап преобработки:
** отдельный файл .R до обработки
** отдельный файл с преодобработанными (“чистыми”) данными - на котором можно спускать алгоритмы, сохранять скрипт обработки и не тратить каждый раз дополнительные усилия на обработку. Так же это удобно, если исходная таблица меняется или дополняется (например, присылают вторую часть данных)
Визуальная инспекция данных – важный этап предварительного анализа данных. Она позволяет заметить очевидные несоответствия и аномалии в данных, и, что немаловажно, “почувствовать” структуру дата фрейма. Какие в нём есть переменные? Что они означают? В каких единицах измеряются? Какой у них диапазон значений?
?quakes
str(quakes)
'data.frame': 1000 obs. of 5 variables:
$ lat : num -20.4 -20.6 -26 -18 -20.4 ...
$ long : num 182 181 184 182 182 ...
$ depth : int 562 650 42 626 649 195 82 194 211 622 ...
$ mag : num 4.8 4.2 5.4 4.1 4 4 4.8 4.4 4.7 4.3 ...
$ stations: int 41 15 43 19 11 12 43 15 35 19 ...
summary(quakes)
lat long depth mag stations
Min. :-38.59 Min. :165.7 Min. : 40.0 Min. :4.00 Min. : 10.00
1st Qu.:-23.47 1st Qu.:179.6 1st Qu.: 99.0 1st Qu.:4.30 1st Qu.: 18.00
Median :-20.30 Median :181.4 Median :247.0 Median :4.60 Median : 27.00
Mean :-20.64 Mean :179.5 Mean :311.4 Mean :4.62 Mean : 33.42
3rd Qu.:-17.64 3rd Qu.:183.2 3rd Qu.:543.0 3rd Qu.:4.90 3rd Qu.: 42.00
Max. :-10.72 Max. :188.1 Max. :680.0 Max. :6.40 Max. :132.00
head(quakes)
tail(quakes)
Загрузим реальный массив с данными для работы
?read.csv
avian <- read.csv("C:/Users/Tony/Desktop/R/Mine/avianHabitat.csv")
Проглядим, что он из себя представляет. Заодно проверяем, чтобы все типы данных считались правильно.
head(avian)
Видим, что все данные считались правильно.
str(avian)
'data.frame': 1070 obs. of 17 variables:
$ Site : chr "BunkerHill27" "BunkerHill27" "BunkerHill27" "BunkerHill27" ...
$ Observer: chr "RA" "RA" "RA" "RA" ...
$ Subpoint: int 1 2 3 4 5 6 7 8 9 10 ...
$ VOR : num 6 4.5 2 2.5 4 2 5.5 4 3.5 3.5 ...
$ PDB : int 3 2 4 3 4 3 3 2 2 2 ...
$ DBHt : num 5.2 3.1 5.5 6.2 5.4 4 5.2 4.4 5.7 4.8 ...
$ PW : int 0 3 1 0 0 0 2 1 1 0 ...
$ WHt : num 0 4.7 5.8 0 0 0 6.3 4.1 5.7 0 ...
$ PE : int 4 3 3 3 3 3 2 2 2 1 ...
$ EHt : num 2.9 4.1 3.9 4 3.5 4.1 2.6 4.3 5.2 1.7 ...
$ PA : int 0 0 0 0 0 0 0 0 0 0 ...
$ AHt : num 0 0 0 0 0 0 0 0 0 0 ...
$ PH : int 4 3 3 4 4 2 4 5 4 5 ...
$ HHt : num 3 3.5 7.5 5 3.7 3.5 5.8 8.2 6.9 5.7 ...
$ PL : int 0 2 0 0 0 0 0 0 0 0 ...
$ LHt : num 0 1 0 0 0 0 0 0 0 0 ...
$ PB : int 0 0 0 0 0 0 0 0 0 0 ...
Посчитаем базовые описательные статистики. Исходя из этого можно сделать визуальную оценку данных. Таким образом, сразу можно обнаружить аномалии, например, если есть переменная, отвечающая за проценты, то сразу понимаем, что минимум не может быть меньше 0, а максимум - больше 100
summary(avian)
Site Observer Subpoint VOR PDB DBHt
Length:1070 Length:1070 Min. : 1.000 Min. : 0.000 Min. :0.0000 Min. : 0.0000
Class :character Class :character 1st Qu.: 3.000 1st Qu.: 0.000 1st Qu.:0.0000 1st Qu.: 0.0000
Mode :character Mode :character Median : 6.000 Median : 1.000 Median :0.0000 Median : 0.0000
Mean : 5.921 Mean : 1.203 Mean :0.8682 Mean : 0.7827
3rd Qu.: 8.000 3rd Qu.: 1.500 3rd Qu.:2.0000 3rd Qu.: 1.2000
Max. :15.000 Max. :19.000 Max. :5.0000 Max. :10.0000
PW WHt PE EHt PA AHt
Min. :0.000 Min. : 0.000 Min. :0.000 Min. :0.0000 Min. :0.00000 Min. : 0.000
1st Qu.:0.000 1st Qu.: 0.000 1st Qu.:1.000 1st Qu.:0.3000 1st Qu.:0.00000 1st Qu.: 0.000
Median :1.000 Median : 0.400 Median :2.000 Median :0.8000 Median :0.00000 Median : 0.000
Mean :1.151 Mean : 1.027 Mean :2.239 Mean :0.9659 Mean :0.04206 Mean : 0.186
3rd Qu.:2.000 3rd Qu.: 1.100 3rd Qu.:3.000 3rd Qu.:1.4000 3rd Qu.:0.00000 3rd Qu.: 0.000
Max. :6.000 Max. :24.500 Max. :6.000 Max. :5.3000 Max. :6.00000 Max. :31.500
PH HHt PL LHt PB
Min. :0.000 Min. :0.000 Min. :0.000 Min. :0.0000 Min. :0.0000
1st Qu.:2.000 1st Qu.:1.400 1st Qu.:0.000 1st Qu.:0.0000 1st Qu.:0.0000
Median :3.000 Median :2.300 Median :1.000 Median :0.2000 Median :0.0000
Mean :2.867 Mean :2.321 Mean :1.652 Mean :0.2685 Mean :0.7318
3rd Qu.:4.000 3rd Qu.:3.100 3rd Qu.:3.000 3rd Qu.:0.5000 3rd Qu.:1.0000
Max. :6.000 Max. :8.200 Max. :6.000 Max. :1.3000 Max. :6.0000
Преодобработка данных крайне важный этап. Известный принцип GIGO: “Garbage in - Garbage out”
Не всегда можно отловить все ошибки считывания данных с помощью функций str, summary и head
Есть ли пропущенные значения? Знак “!” - это логический оператор, который обознаечает NOT. Т.е. фактически мы проверяем, есть ли НЕ законченные наблюдения
any(!complete.cases(avian))
[1] FALSE
или более прямой запрос:
any(is.na(avian))
[1] FALSE
Пропусков нет - вопрос отпадает
N.B! Конструкции вида any(is.na(x)) или any(!complete.cases(data)) после версии R 3.1.0. призвана заменить конструкция anyNA. Работает она быстрее, разумеется. Приятно и то, что она работает со вложенными списками (нужно указать recursive = TRUE)
Чтобы отслеживать такую инфу полезно читать https://cran.r-project.org/src/base/NEWS после очередного релиза полезно
Проверим диапазон процентов Знак “|” - это логический оператор, обозначающий OR
any(avian$PDB < 0 | avian$PDB > 100)
[1] FALSE
Переменная PDB, отвечающая за % покрытия, прошла проверку
Готовим функцию для выполнения повторяющихся операций
Не всегда удобно проверять все переменные подряд. Есть отлаженный механизм, когда повторяющиеся действия заключаем в функцию.
check_percent_range <- function(x) {
any(x < 0 | x > 100)
}
Проверяем PDB
check_percent_range(avian$PDB)
[1] FALSE
check_percent_range(avian$PW)
[1] FALSE
Допустим, все проверили. Все в порядке
Нас могут волновать, разные вопросы преобразования. В задачи преобразования переменных может входить, напрмимер:
* изменение мер измерения (например, из кг в г)
* создание новых переменных, на основе вычисления из имеющихся (например, подсчет ИМТ на основе переменных роста и веса)
* и др.
В дата фрейме avian у нас есть отдельные переменные, характеризующие процент покрытия разных видов. Например, нас интересует, какой общий процент покрытия по всем имеющимся видам. Будет ли он близок к 100%? или в каком-то диапазоне? Это осмысленный вопрос.
Для этого нам нужно:
* создать отдельную переменную
* сложить в новую переменную все имеющиеся проценты
А какие переменные у нас вообще есть? Посмотрим, какие перменные записаны в дата фрейме
names(avian)
[1] "Site" "Observer" "Subpoint" "VOR" "PDB" "DBHt" "PW" "WHt" "PE"
[10] "EHt" "PA" "AHt" "PH" "HHt" "PL" "LHt" "PB"
Теперь начинаем писать код, который сделает, что мы хотим
# Можем выбросить первые четыре переменные сразу
# Дальше видим, что каждая 2-я переменная нас не интересует, поэтому можем воспользоваться конструкцией c(T,F)
coverage_variables <- names(avian)[-(1:4)][c(T, F)]
При помощи такой конструкции взяли только те типы переменных, которые содержат в себе только проценты.
N.B! Две квадратные скобки подряд
Когда допустимо применять две пары квадратных скобок при индексации?
Применять можно всегда. В случае x[1][3] вы берете первый элемент, и в этом векторе длины один пытаетесь обратиться по третьему индексу, что NULL.
Чтобы понять, как работает можно посмотреть на другие варианты
#x[1:3][3], x[c(1,2,4)][1:2][1]
coverage_variables
[1] "PDB" "PW" "PE" "PA" "PH" "PL" "PB"
Чтобы теперь создать новую переменную обратимся к имени с помощью знака “$”, которого в дата фрейме пока нет
# rowSums(avian[ , "колонки с нужными переменными"]) посчитает сумму
avian$total_coverage <- rowSums(avian[ , coverage_variables])
Посмотрим, что такая переменная есть теперь в дата фрейме
head(avian$total_coverage)
[1] 11 13 11 10 11 8
head(avian)
Теперь может оценить разброc по этой перменной
summary(avian$total_coverage)
Min. 1st Qu. Median Mean 3rd Qu. Max.
2.000 8.000 10.000 9.552 11.000 17.000
Видим, что, например, максимальное покрытие видом составляет - 17%, что не очень много.
Можем посмотреть встречаемость тех или иных значений по переменной
table(avian$total_coverage)
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
2 3 4 8 41 98 154 196 227 187 88 35 22 3 1 1
А на основе этого построить бысрый график, например:
plot(table(avian$total_coverage),
main = "Гистограмма общей площади покрытия видами",
type = "h"
)
Гистограму можно построить и с помощью специальной функции
hist(avian$total_coverage)
Можно попробовать разделить графиики распределения в зависимости от места сбора информации. Для начала выясню, откуда вообще собирали информацию
table(avian$Site)
BunkerHill11 BunkerHill12 BunkerHill13 BunkerHill14 BunkerHill15
10 10 10 10 10
BunkerHill16 BunkerHill17 BunkerHill21 BunkerHill22 BunkerHill23
10 10 10 10 10
BunkerHill24 BunkerHill25 BunkerHill26 BunkerHill27 CreteCreek110
10 10 10 10 10
CreteCreek112 CreteCreek114 CreteCreek116 CreteCreek118 CreteCreek12
10 10 10 10 10
CreteCreek120 CreteCreek14 CreteCreek16 CreteCreek18 CreteCreek21
10 10 10 10 10
CreteCreek22 CreteCreek23 CreteCreek24 CreteCreek25 CreteCreek26
10 10 10 10 10
CreteCreek27 CreteCreek28 CreteCreek29 HortonCreek11 HortonCreek110
10 10 10 10 10
HortonCreek111 HortonCreek112 HortonCreek113 HortonCreek114 HortonCreek115
10 10 10 10 10
HortonCreek116 HortonCreek117 HortonCreek118 HortonCreek119 HortonCreek12
10 10 10 10 10
HortonCreek120 HortonCreek121 HortonCreek122 HortonCreek123 HortonCreek124
10 10 10 10 10
HortonCreek125 HortonCreek126 HortonCreek13 HortonCreek14 HortonCreek15
10 10 10 10 10
HortonCreek16 HortonCreek17 HortonCreek18 HortonCreek19 LivingstonCreek11
10 10 10 10 10
LivingstonCreek110 LivingstonCreek111 LivingstonCreek112 LivingstonCreek113 LivingstonCreek114
10 10 10 10 10
LivingstonCreek115 LivingstonCreek116 LivingstonCreek12 LivingstonCreek13 LivingstonCreek14
10 10 10 15 15
LivingstonCreek15 LivingstonCreek16 LivingstonCreek17 LivingstonCreek18 LivingstonCreek19
10 10 15 15 10
LivingstonCreek21 LivingstonCreek210 LivingstonCreek211 LivingstonCreek22 LivingstonCreek23
10 10 10 10 10
LivingstonCreek24 LivingstonCreek25 LivingstonCreek26 LivingstonCreek27 LivingstonCreek28
10 10 10 10 10
LivingstonCreek29 McAdamCreek11 McAdamCreek12 McAdamCreek13 McAdamCreek14
10 15 15 15 15
McAdamCreek15 McAdamCreek16 McAdamCreek17 McAdamCreek18 McAdamCreek21
15 15 15 15 10
McAdamCreek22 McAdamCreek23 McAdamCreek24 McAdamCreek25 McAdamCreek26
10 10 10 10 10
McAdamCreek27
10
Могу попробовать среди этого мяса вычленить индексы строк, содержащие частичные совпадения, с помощью функции grep
grep("BunkerHill", avian$Site)
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
[26] 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
[51] 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
[76] 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
[101] 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
[126] 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
Теперь тэйблом снова смотрю, что я находу так только интересующую меня строку
table(avian$Site[grep("BunkerHill", avian$Site)])
BunkerHill11 BunkerHill12 BunkerHill13 BunkerHill14 BunkerHill15 BunkerHill16 BunkerHill17 BunkerHill21
10 10 10 10 10 10 10 10
BunkerHill22 BunkerHill23 BunkerHill24 BunkerHill25 BunkerHill26 BunkerHill27
10 10 10 10 10 10
Попробую построить гистограму площади покрытия для Bunker Hill-a
hist(avian$total_coverage[grep("BunkerHill", avian$Site)])
Теперь, например, для Livingston Creek
hist(avian$total_coverage[grep("LivingstonCreek", avian$Site)])
Еще какое-то время назад мы ничего не могли сказать о дата фрейме. Простейшее преобразование помогает нам задавать осмысленные вопросы.
Нужно вбить кусок недостающих данных, которые не прислал нам Карлош Линнейс
avian_rest <- read.csv("https://raw.githubusercontent.com/tonytonov/Rcourse/master/R%20programming/avianHabitat2.csv")
Посмотрим, есть ли разница с уже имеющимися данными и нужно ли нам какие-то вносить изменения
head(avian_rest)
Вижу, что данные вообще считались некоректно. Первые 4 строки явно лишние
str(avian_rest)
'data.frame': 23 obs. of 2 variables:
$ Dear.Sir.or.Madam: chr "Here's the rest of our data" "With best regards" "Carlos Linayas" "----data starts from here!----" ...
$ X : chr " sorry for the delay!" " " "" "" ...
Попробую пропустить первые 4 строки при повторном считывании
avian_rest <- read.csv("https://raw.githubusercontent.com/tonytonov/Rcourse/master/R%20programming/avianHabitat2.csv", skip = 4)
Проверяю
head(avian_rest)
Лишние строки успешно пропущены, но замечаю, что в дата фрейме в качестве разделителя используется “;”. По умолчанию аргумент sep = “,”. Сделаю замену.
avian_rest <- read.csv("https://raw.githubusercontent.com/tonytonov/Rcourse/master/R%20programming/avianHabitat2.csv", skip = 4, sep = ";")
Ошибка в read.table(file = file, header = header, sep = sep, quote = quote, :
больше колонок, чем имен для них
Что-то не так с числом колонок. Колонок с данными больше, чем имен. Кажется есть еще 1 лишняя строка. Пробую:
avian_rest <- read.csv("https://raw.githubusercontent.com/tonytonov/Rcourse/master/R%20programming/avianHabitat2.csv", skip = 5, sep = ";")
head(avian_rest)
Сравню с исходным файлом
head(avian)
Преобразование почему-то не сработало. Пробую дальше. Нахожу комментарий к данным при просмотре таблицы вручную и дурацкую подпись в последней колонке. Пробую закоментировать подпись к данным в таблице
avian_rest <- read.csv("https://raw.githubusercontent.com/tonytonov/Rcourse/master/R%20programming/avianHabitat2.csv", skip = 5, sep = ";", quote = "%")
При просмотре вижу, что комментарий исчез. Избавляюсь от подписи
avian_rest["PB...I.removed.Observer.column.since.all.measurements.are.mine"] <- "PB"
Произошла какая-то хрень. Переделаю сначал
avian_rest <- read.csv("https://raw.githubusercontent.com/tonytonov/Rcourse/master/R%20programming/avianHabitat2.csv", skip = 5, sep = ";", quote = "%")
Исправилось частично. В последней колонке куча хрени.Пробую снова. Надеюсь правильно
avian_rest$PB..I.removed..Observer..column.since.all.measurements.are.mine.HortonCreek111.1.3.0.0.0.0.4.3.5.0.0.3.5.0.0.0.HortonCreek111.2.3.0.0.4.18.5.0.0.0.0.4.5.7.0.0.0.HortonCreek111.3.2.0.0.3.11.3.2.3.0.0.4.4.9.1.0.2.0.HortonCreek111.4.3.5.0.0.4.15.8.0.0.0.0.3.4.2.0.0.0.HortonCreek111.5.0.1.0.3.2.0.5.4.0.4.0.0.2.1.4.5.0.3.0.HortonCreek111.6.0.2.0.7.3.0.5.4.0.5.0.0.1.1.6.3.0.5.1.HortonCreek111.7.0.2.0.3.0.0.5.0.4.0.0.2.1.8.5.0.3.0.HortonCreek111.Don.t.remember.0.2.0.7.0.0.5.0.6.0.0.1.1.6.4.0.2.1.....Sorry.about.that..I.messed.up <- avian_rest$PB
??"data.frame"
Читаю справку по дата фрейму. Вроде понимаю, как надо
dimnames(avian_rest$PB..I.removed..Observer..column.since.all.measurements.are.mine.HortonCreek111.1.3.0.0.0.0.4.3.5.0.0.3.5.0.0.0.HortonCreek111.2.3.0.0.4.18.5.0.0.0.0.4.5.7.0.0.0.HortonCreek111.3.2.0.0.3.11.3.2.3.0.0.4.4.9.1.0.2.0.HortonCreek111.4.3.5.0.0.4.15.8.0.0.0.0.3.4.2.0.0.0.HortonCreek111.5.0.1.0.3.2.0.5.4.0.4.0.0.2.1.4.5.0.3.0.HortonCreek111.6.0.2.0.7.3.0.5.4.0.5.0.0.1.1.6.3.0.5.1.HortonCreek111.7.0.2.0.3.0.0.5.0.4.0.0.2.1.8.5.0.3.0.HortonCreek111.Don.t.remember.0.2.0.7.0.0.5.0.6.0.0.1.1.6.4.0.2.1.....Sorry.about.that..I.messed.up) <- "PB"
Ошибка в dimnames(avian_rest$PB..I.removed..Observer..column.since.all.measurements.are.mine.HortonCreek111.1.3.0.0.0.0.4.3.5.0.0.3.5.0.0.0.HortonCreek111.2.3.0.0.4.18.5.0.0.0.0.4.5.7.0.0.0.HortonCreek111.3.2.0.0.3.11.3.2.3.0.0.4.4.9.1.0.2.0.HortonCreek111.4.3.5.0.0.4.15.8.0.0.0.0.3.4.2.0.0.0.HortonCreek111.5.0.1.0.3.2.0.5.4.0.4.0.0.2.1.4.5.0.3.0.HortonCreek111.6.0.2.0.7.3.0.5.4.0.5.0.0.1.1.6.3.0.5.1.HortonCreek111.7.0.2.0.3.0.0.5.0.4.0.0.2.1.8.5.0.3.0.HortonCreek111.Don.t.remember.0.2.0.7.0.0.5.0.6.0.0.1.1.6.4.0.2.1.....Sorry.about.that..I.messed.up) <- "PB" :
'dimnames' применены для не-многомерной матрицы
names(avian_rest)
[1] "Site" "Subpoint" "VOR" "PDB" "DBHt" "PW" "WHt" "PE" "EHt"
[10] "PA" "AHt" "PH" "HHt" "PL" "LHt" "PB"
names(avian_rest$PB..I.removed..Observer..column.since.all.measurements.are.mine.HortonCreek111.1.3.0.0.0.0.4.3.5.0.0.3.5.0.0.0.HortonCreek111.2.3.0.0.4.18.5.0.0.0.0.4.5.7.0.0.0.HortonCreek111.3.2.0.0.3.11.3.2.3.0.0.4.4.9.1.0.2.0.HortonCreek111.4.3.5.0.0.4.15.8.0.0.0.0.3.4.2.0.0.0.HortonCreek111.5.0.1.0.3.2.0.5.4.0.4.0.0.2.1.4.5.0.3.0.HortonCreek111.6.0.2.0.7.3.0.5.4.0.5.0.0.1.1.6.3.0.5.1.HortonCreek111.7.0.2.0.3.0.0.5.0.4.0.0.2.1.8.5.0.3.0.HortonCreek111.Don.t.remember.0.2.0.7.0.0.5.0.6.0.0.1.1.6.4.0.2.1.....Sorry.about.that..I.messed.up) <- "PB"
Ошибка в names(avian_rest$PB..I.removed..Observer..column.since.all.measurements.are.mine.HortonCreek111.1.3.0.0.0.0.4.3.5.0.0.3.5.0.0.0.HortonCreek111.2.3.0.0.4.18.5.0.0.0.0.4.5.7.0.0.0.HortonCreek111.3.2.0.0.3.11.3.2.3.0.0.4.4.9.1.0.2.0.HortonCreek111.4.3.5.0.0.4.15.8.0.0.0.0.3.4.2.0.0.0.HortonCreek111.5.0.1.0.3.2.0.5.4.0.4.0.0.2.1.4.5.0.3.0.HortonCreek111.6.0.2.0.7.3.0.5.4.0.5.0.0.1.1.6.3.0.5.1.HortonCreek111.7.0.2.0.3.0.0.5.0.4.0.0.2.1.8.5.0.3.0.HortonCreek111.Don.t.remember.0.2.0.7.0.0.5.0.6.0.0.1.1.6.4.0.2.1.....Sorry.about.that..I.messed.up) <- "PB" :
попытка присвоения атрибута на NULL
names(avian_rest)
[1] "Site" "Subpoint" "VOR" "PDB" "DBHt" "PW" "WHt" "PE" "EHt"
[10] "PA" "AHt" "PH" "HHt" "PL" "LHt" "PB"
В итоге гуглю, нахожу статью на Stackoverflow
colnames(avian_rest)
[1] "Site" "Subpoint" "VOR" "PDB" "DBHt" "PW" "WHt" "PE" "EHt"
[10] "PA" "AHt" "PH" "HHt" "PL" "LHt" "PB"
colnames(avian_rest)[16] <- "PB"
colnames(avian_rest)
[1] "Site" "Subpoint" "VOR" "PDB" "DBHt" "PW" "WHt" "PE" "EHt"
[10] "PA" "AHt" "PH" "HHt" "PL" "LHt" "PB"
Получилось! Ура.
head(avian_rest)
Теперь видно, почему не работало преобразование на subpoint в integer. В дата фрейме есть пропущенные значения. Попробую их заменить на NA
??data.frame-missing
Ошибка в help.search(c("-", "data.frame", "missing"), package = NULL) :
аргумент ‘pattern’ должен быть одной текстовой строкой
Снова быстро нахожу ответ на Stackoverflow. Пробую
avian_rest <- replace(avian_rest, any(avian_rest) == "Don`t remember", NA)
Ошибка в FUN(X[[i]], ...) :
определено только для таблиц данных со всеми числовыми переменными
Проверю
head(avian_rest)
Замены не произошло. Способ не работает для типа character. Нахожу способ для character
avian_rest[avian_rest == "Don`t remember"] <- NA
head(avian_rest)
Снова не работает.
Стоп.
Приглядываюсь.
Апостроф не тот. Копирую и пробую еще раз
avian_rest[avian_rest == "Don't remember"] <- NA
head(avian_rest)
Ура! На этот раз получилось. Преобразую
as.integer(avian_rest$Subpoint)
[1] NA 1 2 3 4 5 6 7 8 9
head(avian_rest)
Преобразование не сработало, но и хрен с ним, наверное. Остается главная проблема, как это все подшить, учитывая, что нет колонки. Попробую сделать новую
avian_rest[]
Попробую их соедиить так. Может обойдется
merge(avian, avian_rest, by.x = "Subpoint")
Ошибка в merge.data.frame(avian, avian_rest, by.x = "Subpoint") :
'by.x' и 'by.y' определяют разные номера колонок
Из готовых функций нахожу такую только в пакете dplyr ` Остается нерешенной проблема преобразования. Снова нахожу способ на Stack-е
avian_rest$Subpoint <- as.integer(as.character(avian_rest$Subpoint))
library(dplyr)
Было 12 предупреждений (введите warnings() чтобы их просмотреть)
dplyr::bind_rows(avian, avian_rest)
Ура! Теперь наконец-то могу пересчитать показатели. Интересно, как выглядит хвост?
str(avian)
'data.frame': 1070 obs. of 18 variables:
$ Site : chr "BunkerHill27" "BunkerHill27" "BunkerHill27" "BunkerHill27" ...
$ Observer : chr "RA" "RA" "RA" "RA" ...
$ Subpoint : int 1 2 3 4 5 6 7 8 9 10 ...
$ VOR : num 6 4.5 2 2.5 4 2 5.5 4 3.5 3.5 ...
$ PDB : int 3 2 4 3 4 3 3 2 2 2 ...
$ DBHt : num 5.2 3.1 5.5 6.2 5.4 4 5.2 4.4 5.7 4.8 ...
$ PW : int 0 3 1 0 0 0 2 1 1 0 ...
$ WHt : num 0 4.7 5.8 0 0 0 6.3 4.1 5.7 0 ...
$ PE : int 4 3 3 3 3 3 2 2 2 1 ...
$ EHt : num 2.9 4.1 3.9 4 3.5 4.1 2.6 4.3 5.2 1.7 ...
$ PA : int 0 0 0 0 0 0 0 0 0 0 ...
$ AHt : num 0 0 0 0 0 0 0 0 0 0 ...
$ PH : int 4 3 3 4 4 2 4 5 4 5 ...
$ HHt : num 3 3.5 7.5 5 3.7 3.5 5.8 8.2 6.9 5.7 ...
$ PL : int 0 2 0 0 0 0 0 0 0 0 ...
$ LHt : num 0 1 0 0 0 0 0 0 0 0 ...
$ PB : int 0 0 0 0 0 0 0 0 0 0 ...
$ total_coverage: num 11 13 11 10 11 8 11 10 9 8 ...
Но у меня что-то не так с количеством наблюдений. У меня 1080, а должно быть 1088. Может dplyr не объединяет их окончательно. Хз. На данном этапе все слишком запутано. Попробую изначально прочитать файл по-нормальному без заморочек, как предлагается в комментариях
read.csv(sep = ";", skip = 5, header = T, comment.char = "%", quote = "", na.strings = "Don't remember", file = 'https://raw.githubusercontent.com/tonytonov/Rcourse/master/R%20programming/avianHabitat2.csv')
Попробую теперь объединить dplyr-ом
dplyr::bind_rows(avian, avian_rest)
1080 наблюдений. Бля
str(bind_rows(avian, avian_rest))
'data.frame': 1080 obs. of 18 variables:
$ Site : chr "BunkerHill27" "BunkerHill27" "BunkerHill27" "BunkerHill27" ...
$ Observer : chr "RA" "RA" "RA" "RA" ...
$ Subpoint : int 1 2 3 4 5 6 7 8 9 10 ...
$ VOR : num 6 4.5 2 2.5 4 2 5.5 4 3.5 3.5 ...
$ PDB : int 3 2 4 3 4 3 3 2 2 2 ...
$ DBHt : num 5.2 3.1 5.5 6.2 5.4 4 5.2 4.4 5.7 4.8 ...
$ PW : int 0 3 1 0 0 0 2 1 1 0 ...
$ WHt : num 0 4.7 5.8 0 0 0 6.3 4.1 5.7 0 ...
$ PE : int 4 3 3 3 3 3 2 2 2 1 ...
$ EHt : num 2.9 4.1 3.9 4 3.5 4.1 2.6 4.3 5.2 1.7 ...
$ PA : int 0 0 0 0 0 0 0 0 0 0 ...
$ AHt : num 0 0 0 0 0 0 0 0 0 0 ...
$ PH : int 4 3 3 4 4 2 4 5 4 5 ...
$ HHt : num 3 3.5 7.5 5 3.7 3.5 5.8 8.2 6.9 5.7 ...
$ PL : int 0 2 0 0 0 0 0 0 0 0 ...
$ LHt : num 0 1 0 0 0 0 0 0 0 0 ...
$ PB : int 0 0 0 0 0 0 0 0 0 0 ...
$ total_coverage: num 11 13 11 10 11 8 11 10 9 8 ...
В общем, нормально он не объединяет в таком формате почему-то.
str(avian_rest)
'data.frame': 10 obs. of 16 variables:
$ Site : chr "HortonCreek111" "HortonCreek112" "HortonCreek112" "HortonCreek112" ...
$ Subpoint: int NA 1 2 3 4 5 6 7 8 9
$ VOR : int 0 0 0 0 0 0 0 0 0 0
$ PDB : int 1 1 2 1 2 0 0 0 3 0
$ DBHt : num 0.4 0.8 0.5 0.1 0.3 0 0 0 0.7 0
$ PW : int 2 0 0 0 0 0 0 2 0 0
$ WHt : num 0.3 0 0 0 0 0 0 0.3 0 0
$ PE : int 3 3 3 3 3 4 2 3 0 2
$ EHt : num 0.3 0.3 0.4 0.2 0.2 0.7 0.3 0.3 0 0.2
$ PA : int 0 0 0 0 0 0 0 0 0 0
$ AHt : int 0 0 0 0 0 0 0 0 0 0
$ PH : int 2 1 2 1 1 1 2 2 1 2
$ HHt : num 1.3 0.9 0.7 0.5 0.5 0.5 0.7 0.8 3.1 0.7
$ PL : int 5 4 3 4 4 2 3 4 5 1
$ LHt : num 0.4 0.4 0.1 0.1 0.1 0.1 0.3 0.4 0.5 0.3
$ PB : int 0 1 1 2 1 2 3 2 0 4
Куда-то делись 8 наблюдений. Перечитаю заново
read.csv(sep = ";", skip = 5, comment.char = "%", quote = "", na.strings = "Don't remember", file = 'https://raw.githubusercontent.com/tonytonov/Rcourse/master/R%20programming/avianHabitat2.csv')
str(avian_rest)
'data.frame': 10 obs. of 16 variables:
$ Site : chr "HortonCreek111" "HortonCreek112" "HortonCreek112" "HortonCreek112" ...
$ Subpoint: int NA 1 2 3 4 5 6 7 8 9
$ VOR : int 0 0 0 0 0 0 0 0 0 0
$ PDB : int 1 1 2 1 2 0 0 0 3 0
$ DBHt : num 0.4 0.8 0.5 0.1 0.3 0 0 0 0.7 0
$ PW : int 2 0 0 0 0 0 0 2 0 0
$ WHt : num 0.3 0 0 0 0 0 0 0.3 0 0
$ PE : int 3 3 3 3 3 4 2 3 0 2
$ EHt : num 0.3 0.3 0.4 0.2 0.2 0.7 0.3 0.3 0 0.2
$ PA : int 0 0 0 0 0 0 0 0 0 0
$ AHt : int 0 0 0 0 0 0 0 0 0 0
$ PH : int 2 1 2 1 1 1 2 2 1 2
$ HHt : num 1.3 0.9 0.7 0.5 0.5 0.5 0.7 0.8 3.1 0.7
$ PL : int 5 4 3 4 4 2 3 4 5 1
$ LHt : num 0.4 0.4 0.1 0.1 0.1 0.1 0.3 0.4 0.5 0.3
$ PB : int 0 1 1 2 1 2 3 2 0 4
Почему-то все время пишет 10 наблюдений. Может, считает количество полных наблюдений? Хотя, если посчитать вручную, то получаетс я 18. Не понимаю. Ладно, пофиг надо объединять.
av_fin <- dplyr::bind_rows(avian, avian_rest)
av_fin
coverage_variables <- names(av_fin)[-(1:4)][c(T, F)]
av_fin$total_coverage <- rowSums(av_fin[ , coverage_variables])
summary(av_fin$total_coverage)
Min. 1st Qu. Median Mean 3rd Qu. Max.
2.000 8.000 10.000 9.562 11.000 17.000
av_fin
av_fin$total_coveragei <- NULL
av_fin
Все-таки подозреваю проблему в объединении. Буду пробовать по-другому.
read.csv(sep = ";", skip = 5, comment.char = "%", quote = "", na.strings = "Don't remember", file = 'https://raw.githubusercontent.com/tonytonov/Rcourse/master/R%20programming/avianHabitat2.csv')
colnames(avian_rest)
[1] "Site" "Subpoint" "VOR" "PDB" "DBHt" "PW" "WHt" "PE" "EHt"
[10] "PA" "AHt" "PH" "HHt" "PL" "LHt" "PB"
colnames(avian_rest[2]) <- "Observer"
colnames(avian_rest)
[1] "Site" "Subpoint" "VOR" "PDB" "DBHt" "PW" "WHt" "PE" "EHt"
[10] "PA" "AHt" "PH" "HHt" "PL" "LHt" "PB"
avian_rest$Observer <- "KL"
head(avian_rest)
colnames(avian_rest)
[1] "Site" "Subpoint" "VOR" "PDB" "DBHt" "PW" "WHt" "PE" "EHt"
[10] "PA" "AHt" "PH" "HHt" "PL" "LHt" "PB" "Observer"
avian_rest <- avian_rest[ , c("Site", "Observer", "Subpoint", "VOR", "PDB", "DBHt", "PW", "WHt", "PE", "EHt" ,"PA", "AHt", "PH", "HHt", "PL", "LHt", "PB")]
avian_rest
av <- merge(avian, avian_rest, all = T)
av
av$total_coveragei <- NULL
av
coverage_variables <- names(av)[-(1:4)][c(T, F)]
av$total_coverage <- rowSums(av[ , coverage_variables])
summary(av$total_coverage)
Min. 1st Qu. Median Mean 3rd Qu. Max.
2.000 8.000 10.000 9.562 11.000 17.000
av
Фух. Решил таки задачу. В итоге ответ мне не засчитывали, тыкнул просто на подбор.
avian <- read.csv("https://raw.githubusercontent.com/tonytonov/Rcourse/master/R%20programming/avianHabitat.csv")
coverage_variables <- names(avian)[-(1:4)][c(T, F)]
avian2 <- read.csv("https://raw.githubusercontent.com/tonytonov/Rcourse/master/R%20programming/avianHabitat2.csv",
sep = ";", na.strings = "Don't remember", skip = 5, comment.char = "%")
avian2
avian2$Observer <- "CL" # для красоты
avian2
avian3 <- merge(avian, avian2, all = T)
avian3
avian3$total_coverage = rowSums(avian3[coverage_variables])
summary(avian3)[4, "total_coverage"]
[1] "Mean : 9.572 "
avian3
На массиве avianHabitat найдите максимальные высоты по каждому виду растений и отсортируйте эти виды по убыванию, от самого высокого к самому низкому
Общий глоссарий для этого урока:
avian$total_coveragei <- NULL
str(avian)
'data.frame': 1070 obs. of 17 variables:
$ Site : chr "BunkerHill27" "BunkerHill27" "BunkerHill27" "BunkerHill27" ...
$ Observer: chr "RA" "RA" "RA" "RA" ...
$ Subpoint: int 1 2 3 4 5 6 7 8 9 10 ...
$ VOR : num 6 4.5 2 2.5 4 2 5.5 4 3.5 3.5 ...
$ PDB : int 3 2 4 3 4 3 3 2 2 2 ...
$ DBHt : num 5.2 3.1 5.5 6.2 5.4 4 5.2 4.4 5.7 4.8 ...
$ PW : int 0 3 1 0 0 0 2 1 1 0 ...
$ WHt : num 0 4.7 5.8 0 0 0 6.3 4.1 5.7 0 ...
$ PE : int 4 3 3 3 3 3 2 2 2 1 ...
$ EHt : num 2.9 4.1 3.9 4 3.5 4.1 2.6 4.3 5.2 1.7 ...
$ PA : int 0 0 0 0 0 0 0 0 0 0 ...
$ AHt : num 0 0 0 0 0 0 0 0 0 0 ...
$ PH : int 4 3 3 4 4 2 4 5 4 5 ...
$ HHt : num 3 3.5 7.5 5 3.7 3.5 5.8 8.2 6.9 5.7 ...
$ PL : int 0 2 0 0 0 0 0 0 0 0 ...
$ LHt : num 0 1 0 0 0 0 0 0 0 0 ...
$ PB : int 0 0 0 0 0 0 0 0 0 0 ...
heights <- avian[-c(1:5)][c(T, F)]
heights_max <- apply(heights, 2, max)
sort(heights_max, decreasing = T)
AHt WHt DBHt HHt EHt LHt
31.5 24.5 10.0 8.2 5.3 1.3
?data.frame
?str
?rownames, ?colnames, ?dimnames, ?nrow, ?ncol, ?dim
?subset, ?rbind, ?cbind, ?merge
?read.table (?read.csv, ?read.delim)
?write.table (?write.csv, ?write.delim)
?complete.cases, ?na.omit
?write.table (?write.csv)