#!/usr/bin/env python # coding: utf-8 # # 1. Обзор библиотеки pandas, важность подготовки данных # # ## 1.1. [Pandas](http://pandas.pydata.org/) - библиотека Python для анализа данных # # * Быстрая и эффективная работа с объектами таблиц (DataFrame) с индексацией; # * **Чтение и запись данных между данными в памяти компьютера и файлами в разных форматах: CSV, текстовые файлы, Microsoft Excel, SQL-базы данных, HDF5;** # * **Обработка пропущенных и неформатированных данных;** # * Изменение формы, расположения, структуры данных; # * Срезы на основе индексов и названий колонок, создание подмножеств для больших объёмов данных; # # Основными структурами данных в pandas являются классы *Series* и *DataFrame*. # # **Series** - это одномерный индексированный массив данных одного типа. # # **DataFrame** – двухмерная структура данных, таблица, каждый столбец которой содержит данные одного типа. # # Часто загружаемые с помощью pandas данные хранятся как таблицы. Популярные форматы таблиц: # - .csv = Comma Separated Valuse, .tsv = Tab Separated Values, # - Microsoft Excel: .xls, .xlsx, # - HDF5, # - базы данных SQL. # # Сегодня мы познакомимся с чтением данных из формата CSV, фильтрацией и базовой подготовкой данных для анализа. # ## 1.2. Признаки (features) в анализе данных. Категориальные и числовые признаки # # Наиболее распространённая задача анализа данных - обучение с учителем. Имеется множество объектов и множество возможных ответов. Существует некоторая зависимость между ответами и объектами, но она неизвестна. Известна только конечная совокупность прецедентов — пар «объект, ответ», называемая обучающей выборкой. На основе этих данных требуется восстановить зависимость, то есть построить алгоритм, способный для любого объекта выдать достаточно точный ответ. (По материалу [machinelearning.ru](http://www.machinelearning.ru/wiki/index.php?title=%D0%9E%D0%B1%D1%83%D1%87%D0%B5%D0%BD%D0%B8%D0%B5_%D1%81_%D1%83%D1%87%D0%B8%D1%82%D0%B5%D0%BB%D0%B5%D0%BC).) # # Часто встречающимся типом входных данных является **признаковое описание** (матрица объекты-признаки). Каждый объект описывается набором своих характеристик, называемых признаками. Признаки могут быть числовыми или нечисловыми. # # **Числовые признаки** - характеристики данных, выраженные в числах: возраст, количество, размер детали, цена и т. д. Чаще всего такие признаки не требуют особой обработки. # # **Категориальные признаки** - определяют принадлежность к какой-то категории. Примеры: пол, город, время года, номер группы, категория товаров и т.п. Для автоматической обработки таких признаков вместо исходного значения значения категории (например, "М", "Ж" или "Москва", "Лондон") часто необходим перевод в числовую форму. # # Подробнее о кодировке категориальных признаков: # https://habr.com/ru/company/ods/blog/326418/ # http://datareview.info/article/universalnyj-podxod-pochti-k-lyuboj-zadache-mashinnogo-obucheniya/ # # Иногда выделяют **текстовые признаки**. Примеры: полное имя, комментарий, описание. Такие признаки могут оказаться незначимыми в задаче, тогда их можно исключить, иначе к ним тоже применяется обработка и кодировка. # **Подготовка данных к анализу** включает в себя много этапов: очистка и исправление неверных данных, отбор и кодировка признаков, трансформация данных, удаление и создание новых признаков и т. д. # # Подробная классификация процедур подготовки данных: http://www.machinelearning.ru/wiki/images/9/91/PZAD2017_07_datapreprocessing.pdf # In[1]: # Loading (importing) pandas module with often used alias "pd" # Загрузка модуля pandas с коротким именем pd import pandas as pd # load Excel file with pandas as an example # Зазгрузка таблицы Excel excel_file = 'mov.xls' df = pd.read_excel(excel_file) # Review top rows of data # Просмотр верхней части таблицы df.head() # # 2. Аккуратные данные (Tidy Data) # # ## 2.1. Принципы аккуратных данных # # **“Data cleaning is one of the most frequent task in data science. No matter what kind of data you are dealing with or what kind of analysis you are performing, you will have to clean the data at some point.”** -- Jean-Nicholas Hould http://www.jeannicholashould.com/tidy-data-in-python.html # # "**Аккуратные данные**" - термин и набор правил для организации данных при статистических исследованиях из статьи Hadley Wickham, **[Tidy Data](http://www.jstatsoft.org/v59/i10)**, Vol. 59, Issue 10, Sep 2014, Journal of Statistical Software. # # * **Переменная (variable)** - оценка какого-то атрибута. Рост, вес, пол, день недели, размер... Переменная содержит все значения, которые отображают один и тот же атрибут всех объектов. # * **Значение (value)**: конкретный результат измерения атрибута. 152 см, 80 кг, М/Ж, XXL. Каждое значение принадлежит переменной и наблюдению. # * **Наблюдение (observation)** содержит все значения атрибутов, измеренные для одного и того же объекта (такого как человек, день, кинофильм). # # #### Три принципа аккуратных данных (Tidy Data) [http://vita.had.co.nz/papers/tidy-data.pdf] # 1. Каждая переменная формирует колонку и имеет значения # 2. Каждое наблюдение формирует строку (ряд) # 3. Каждый вид эксперимента формирует таблицу. То есть каждый факт выражается только в одном месте. Примеры: баллы студента по разным предметам и данные самого студента должны быть в разных таблицах, не должно быть дубликатов и разночтений. # 4. (При наличии многих таблиц, нужно включать колонки, которые связывают их https://en.wikipedia.org/wiki/Tidy_data) # # Иллюстрация принципов аккуратных данных из статьи https://r4ds.had.co.nz/tidy-data.html # ![Вид CSV файла](http://antakova.ru/wp-content/uploads/2019/01/tidy1.png "Принципы аккуратных данных") # ## 2.2. Распространённые проблемы неаккуратности данных # # Связанные с организацией данных в одной таблице: # * Заголовки колонок - это значения, а не имена переменных # * Несколько переменных хранятся в одной колонке # * Переменные хранятся в колонках и строках # # Связанные с организацией группы таблиц: # * Много типов наблюдений хранится в одной таблице # * Один и тот же тип наблюдений хранится во многих таблицах # # Наш фокус в этом мастер-классе - организация данных в **_одной таблице_**. # # ### Пример: заголовки колонок - это не имена переменных # # Из статьи [Tidy Data](http://vita.had.co.nz/papers/tidy-data.pdf) # # В этой таблице заголовок показывает доход в нескольких колонках. # # | religion | 10k-20k | 20k-30k | # | -------------|:-------------:|----------:| # | Agnostic | 27 | 34 | # | Atheist | 12 | 25 | # | Buddhist | 20 | 27 | # # Переменные в этом наборе - вид религии, доход (категориальный признак) и количество (или частота) людей такого дохода и религии. Для исправления этой таблицы по принципу аккуратных данных нужно из доход сделать переменной-колонкой, а её значения из бывших колонок сделать строками. # # | religion | income | frequency | # | -------------|:-------------:|----------:| # | Agnostic | 10k-20k | 27 | # | Agnostic | 20k-30k | 34 | # | Atheist | 10k-20k | 12 | # | Atheist | 20k-30k | 25 | # | Buddhist | 10k-20k | 20 | # | Buddhist | 20k-30k | 27 | # # ### Несколько переменных хранятся в одной колонке # # Источник примера - [tutorial](http://garrettgman.github.io/tidying/) # # Колонка "ключ" (key) меняет тип переменной, представленной в соседней колонке, и колонка "значение" value имеет либо количество случаев cases, либо общую численность населения в зависимости от ключа. Это небоходимо разделить по колонкам. # # | country | year | key | value | # | -------------|:----------:|-----------:|-----------:| # | Afghanistan | 1999 | cases | 745 | # | Afghanistan | 1999 | population | 19987071 | # | Afghanistan | 2000 | cases | 2666 | # | Afghanistan | 2000 | population | 20595360 | # | Brazil | 1999 | cases | 37737 | # | Brazil | 1999 | population | 172006362 | # | Brazil | 2000 | cases | 80488 | # | Brazil | 2000 | population | 174504898 | # # В такой таблице неудобно считать средние, максимумы или минимумы по значениям cases, population. # Аккуратное и более удобное расположение данных - создать колонки cases, population. # # | country | year | cases | population | # | -------------|:----------:|-----------:|-----------:| # | Afghanistan | 1999 | 745 | 19987071 | # | Afghanistan | 2000 | 2666 | 20595360 | # | Brazil | 1999 | 37737 | 172006362 | # | Brazil | 2000 | 80488 | 174504898 | # # ### Переменные хранятся в колонках и строках # # **Пример 1.** Иллюстрация не полностью аккуратных данных из статьи http://garrettgman.github.io/tidying/ # ![Переменные в колонках и строка](tidy7.png "Не самые аккуратные данные") # # **Пример 2.** По материалу https://habr.com/ru/post/248741/ # # Несколько студентов учились по разным предметам (classes) в течение семестра (term) и сдавали тесты в середине семестра (midterm) и в конце (final). Имеется таблица оценок студентов по всем тестам, которые они сдали. # # | name | test | class1 | class2 | class3 | # | ----------|:------------:|-----------:|-------:|-------:| # | Sally | midterm | A | NA | NA | # | Sally | final | C | NA | NA | # | Jeff | midterm | NA | D | A | # | Jeff | final | NA | A | C | # | Roger | midterm | NA | NA | A | # | Roger | final | NA | NA | C | # # Столбцы class1, class2, class3 содержат значения одной переменной class. А значения столбца test (midterm, final) должны быть переменными и содержать результат теста для каждого студента. # # Создадим новую переменную class со значениями 1-3 и раскроем значения столбца test в переменные final-score и midterm-score. # # | name | class | final-score | midterm-score | # | ----------|:------------:|------------:|--------------:| # | Sally | 1 | C | A | # | Jeff | 2 | A | D | # | Jeff | 3 | C | A | # | Roger | 3 | C | A | # # 3. Загрузка файлов CSV через Excel и pandas # # ## 3.1. Просмотр "сырого" файла CSV # # ![Вид CSV файла](http://antakova.ru/wp-content/uploads/2019/01/csv.png "CSV файл") # # ## 3.2. Удобный просмотр файла CSV с помощью Excel # # Метод получения Excel таблицы из CSV - это команда в меню **Data > Text to Columns**. В диалоге перевода данных в Excel много параметров (тип разделения, разделитель, что делать с дополнительными пробельными символами и т. д.). Результат - читаемая таблица. # # ![Обработанный CSV в Excel](http://antakova.ru/wp-content/uploads/2019/01/excel.jpg "Обработанный CSV в Excel") # # ## 3.3. Загрузка CSV через методы pandas. Настройка параметров загрузки # In[2]: # Read data from file 'winequality-red.csv' in the same directory that your python script # Простое чтение файла без параметров wine_filename = "winequality-red.csv" data = pd.read_csv(wine_filename) # Check top/head lines of loaded data, but the table seems strange # Убедимся, что данные присутствуют, однако таблица не выглядит верной data.head() # In[3]: # Loading CSV file from WEB (URL) # Загрузка файла по WEB-адресу # May not work undef proxy url_csv = 'https://vincentarelbundock.github.io/Rdatasets/csv/boot/amis.csv' df2 = pd.read_csv(url_csv) df2.head() # In[4]: help(pd.read_csv) # In[5]: # Basic parameters for data loading from CSV # Простые параметры для настройки загрузки CSV # delimiter - разделитель значений в CSV-файле data = pd.read_csv(wine_filename, delimiter=';') data.head() # In[6]: # Dataset has description in first row and one empty row, we skip them with skiprows parameter # Файл содержит краткое описание данных в первой строке и пустую строку, пропустим их с помощью параметра skiprows data = pd.read_csv(wine_filename, delimiter=';', skiprows = 2) data.head() # In[7]: # Choose columns of interest with usecols parameter # Выбор отдельных колонок для анализа с помощью параметра usecols по списку названий или номеров # usecols = ['col_name1', 'col_name2'] or usecols=[1, 2, 5] data = pd.read_csv(wine_filename, delimiter=';', skiprows = 2, usecols = ['residual sugar', 'density', 'alcohol', 'quality']) data.head() # ## 3.5. Обзор данных: head(), tail(), shape, columns, info(), describe() # In[8]: # Check the end of data # Просмотр последних строк данных print("data.tail()") print(data.tail()) # Get dimensions of data table # Узнаем размеры таблицы данных print() print("data.shape") print(data.shape) # Print list of columns in data # Распечатаем список колонок в таблице данных print() print("data.columns") print(data.columns) # Print basic information about dataset # Узнаем описание таблицы данных print() print("data.info()") print(data.info()) # Метод describe() показывает основные статистические характеристики данных по каждому числовому признаку (типы int64 и float64): число непропущенных значений, среднее, стандартное отклонение, диапазон, медиану, 0.25 и 0.75 квартили. # In[9]: data.describe() # # 4. Поиск некорректных данных с pandas # ## 4.1 Просмотр данных, чтение строк и столбцов c методами loc, iloc # # По материалу https://www.shanelynn.ie/select-pandas-dataframe-rows-and-columns-using-iloc-loc-and-ix/ # ![Выбор данных с помощью loc, iloc](http://antakova.ru/wp-content/uploads/2019/01/pandas_selection.png "Выбор данных с помощью loc, iloc") # In[10]: # Selection of data by row or col position (iloc) # Выбор данных по строке и колонке - по нумерованной позиции iloc # Print row 3 # Вывод строки с индексом 3 row3 = df.iloc[3] print("row3 type") print(type(row3)) print() print("row3 contents:") print(row3) # Create sub-dataFrame with list of row indexes and a slice of columns # Создание подтаблицы по индексам колонок и строк print() sub_df1 = df.iloc[[1,2,4],0:2] print(type(sub_df1)) print(sub_df1) # In[11]: # Selection of data by label with loc[rows, columns] # Выбор данных по названиям (label) # Example: all rows and 2 named columns # Пример: все строки (:) и две колонки списком имён sub_frame1 = df.loc[:, ['Language', 'Country']] print(sub_frame1.head()) print() # In this data frame row index is just numbers, rows don't have names # Example: rows 0, 1, 2 and a range of columns sub_frame2 = df.loc[0:2, 'Language':'Budget'] print(sub_frame2.head()) # ## 4.2. Поиск пропущенных данных # В разных типах таблиц пропущенные данные могут выглядеть как: # * *np.nan* - это специальное значение из библиотеки numpy (np), # * пустые значения, # * неподходящие значения: пробельные символы, мусор # # В библиотеке pandas почти все пропущенные данные по умолчанию выражаются как **np.nan** # ### Задание: с помощью методов loc, iloc и здравого смысла исправить рейтинг фильма со значением "Unrated" # In[12]: # Example in our small dataset of movies # Пример в подтаблице фильмов рейтинг - не установлен и некоторые значения NaN. # Content Rating = Unrated и Aspect Ratio = NaN # How to fix "Unrated" # Content rating should be set up according to # https://en.wikipedia.org/wiki/Motion_Picture_Association_of_America_film_rating_system # Как исправить "Unrated" - специалист по данным должен принять решение. df.head() # In[13]: na_mask = sub_frame2.isna() print(na_mask) print() # Example how to use: count NA values in one column # Пример: вычисление количества пропущенных значений в одной колонке для полной таблицы budget_col = df.loc[:, 'Budget'] budget_col_na = budget_col.isna() print('Budget column in whole movies dataset has this count of NaN values:') print(budget_col_na.sum()) # ## 4.3. Некорректные данные # # Данные могут присутствовать в таблице, но иметь проблемы: # * неверный формат, # * не подходить как категория признака, # * иметь дубликаты, # * содержать неточную информацию или ошибки # * и другие :) # In[14]: # 1 example on mov.xls: see rows 8, 9 column Country = "usa", not "USA" # 2 example on mov.xls: see row 7, column Year = 2010-2011 seems incorrect # 4 example on mov.xls: see rows 5 and 6, this is the same movie twice df.head(10) # # 5. Исправление некорректных данных # # ## 5.1. Удаление или замена значениями данных N/A (NaN) # In[15]: # drop missing data # Удаление строк с отсутствующими данными df_without_na = df.dropna(how='any') df_without_na.head() # In[16]: # Simple fill missing data with 0 value # Простая замена отсутствующих данных нулями # https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.fillna.html df_filled = df.fillna(value=0) df_filled.head() # In[17]: # fill NA budget with some mean budget for these films # заполним пустой бюджет фильма средним значением по этой колонке mean = df['Budget'].mean() print('mean film budget is') print(mean) print() # inplace - значит заполнять в исходном датаFrame, а не только в возвращаемом новом df['Budget'].fillna(mean, inplace=True) df.head() # ## 5.2. Обработка строк для однотипного форматирования данных # In[26]: # load Excel file with pandas as an example # Зазгрузка таблицы Excel # Using encoding parameter because unicode defaiult encoder gives some errors on content file = 'mov.csv' df = pd.read_csv(file, encoding="ISO-8859-1", delimiter=';'); # Review top rows of data # Просмотр верхней части таблицы df.head() # In[19]: # Pay attention that dtype of "Year" is object, not a value # Because there are some years like 2010-2011 df.dtypes # In[20]: df.Year # In[21]: # Replace " ?" first and then choose the ending year df.Year = df.Year.replace("2008 ?", "2008") df.Year # In[22]: # Choose the ending year as film year # Выберем год окончания как год фильма def getEndingYear(str): return str[-4:] df['Year'] = df['Year'].apply(getEndingYear) df.Year # In[23]: # Now covert year to int type # Теперь колонка с годом преобразуется в число целого типа df['Year'] = pd.to_numeric(df['Year']) df.dtypes # ## 5.3. Упражнение: исправить проблемы данных в колонке 'Country' # In[24]: # Hint 1: issues in this column: 'Official site' value, 'canada' and 'Canada', 'USA' and 'usa', # Совет: проблемы в этой колонке - строчные и прописные буквы, неверное название страны 'Official site' # We can use functions from pandas.str # Можно использовать функции pandas для строк # dataFrame.Column.str.lower() # Converts all characters to lowercase. # dataFrame.Column.str.upper() # Converts all characters to uppercase. # Look at column to see its data problems # Просмотр колонки для визуального определения проблем с данными df.Country # In[25]: # Hint 2 # print what is in row 33 where Country == Official site # Распечатаем строку 33, чтобы понять, для какого фильма неверно указана страна # Hint 2 - find out the real country of issuing this film here: https://www.imdb.com/title/tt1555064/ # Можно узнать, в какой стране выпущен этот фильм на сайте https://www.imdb.com/title/tt1555064/ df.loc[33, :] # # 6. Cтатьи для самостоятельного изучения # # ### 6.1. Загрузка и обработка файлов CSV c Pandas # # * [Python Pandas read_csv – Load Data from CSV Files](https://www.shanelynn.ie/python-pandas-read_csv-load-data-from-csv-files/) # * [Interactive online tutorial for reading CSV with pandas from DataCamp](https://www.datacamp.com/community/tutorials/pandas-read-csv) # # ### 6.2. Подготовка данных с Pandas, работа с признаками, создание аккуратных данных # # * [Selecting Subsets of Data in Pandas: Part 1, by Ted Petrou](https://medium.com/dunder-data/selecting-subsets-of-data-in-pandas-6fcd0170be9c) # * [Открытый курс машинного обучения. Тема 1. Первичный анализ данных с Pandas](https://habr.com/ru/company/ods/blog/322626/) # * [Продвинутая подготовка данных. Открытый курс машинного обучения. Тема 6. Построение и отбор признаков](https://habr.com/ru/company/ods/blog/325422/) # * [Подготовка данных к анализу на языке R. Data tidying: Подготовка наборов данных для анализа на конкретных примерах](https://habr.com/ru/post/248741/)