Pandas это очень мощная библиотека с множеством полезных функций, ею можно пользаться много лет так и не использовав весь ее потенциал. Цель воркшопа ознакомить вас основами, это:
Чтение и запись данных.
Пониманимание разных типов данных в Pandas.
Работа с текстовыми данными и timeseries.
Выбор данных.
Группировка.
Мы будем использовать датасет Amazon Product с отзывами о продуктах на Амазоне, его собрал Julian McAuley.
Датасет выглядит таким образом:
reviewerID - ID of the reviewer, e.g. A2SUAM1J3GNN3B
asin - ID of the product, e.g. 0000013714
reviewerName - name of the reviewer
helpful - helpfulness rating of the review, e.g. 2/3
reviewText - text of the review
overall - rating of the product
summary - summary of the review
unixReviewTime - time of the review (unix time)
reviewTime - time of the review (raw)
In [57]:
import pandas as pd
print("Pandas version: {}".format(pd.__version__))
# опции отображения
pd.options.display.max_rows = 6
pd.options.display.max_columns = 6
pd.options.display.width = 100
In [59]:
import gzip
# датасет на 47 мегабайт, мы возьмем только 10
review_lines = gzip.open('data/reviews/reviews_Clothing_Shoes_and_Jewelry_5.json.gz', 'rt').readlines(10*1024*1024)
len(review_lines)
Out[59]:
Теперь мы получили list
с текстовыми строками, нам нужно преобразовать их в dict
и передать в DataFrame
.
Здесь json.loads
- преобразует текстовые строки в dict
.
In [42]:
import json
df = pd.DataFrame(list(map(json.loads, review_lines)))
Теперь мы можем взглянуть, что собой представляют наши данные. DataFrame позволяет их вывести в такой наглядной таблице.
In [72]:
df
Out[72]:
Данные вначале нашего df
In [73]:
df.head()
Out[73]:
Данные вконце df
In [75]:
df.tail()
Out[75]:
In [76]:
df.describe()
Out[76]:
In [61]:
# ваш код здесь, используйте tab для того, чтобы увидеть список доступных для вызова функций
Pandas I/O API это набор высокоуровневых функций, которые можно вызвать как pd.read_csv().
to_csv
to_excel
to_hdf
to_sql
to_json
...
read_csv
read_excel
read_hdf
read_sql
read_json
...
df.info
позволяет нам получить сводную информацию про df
: сколько в нем строк, названия и типы столбцов, сколько он занимает памяти...
Мы видим, что столбец unixReviewTime
(время, когда ревью было оставленно) имеет тип int64
, давайте преобразуем его в datetime64
для более удобной работы с временными данными.
In [66]:
df.info()
Out[66]:
In [63]:
df['unixReviewTime'] = pd.to_datetime(df['unixReviewTime'], unit='s')
pd.to_datetime?
Теперь мы видим, что столбец был преобразован в нужный нам тип данных.
In [64]:
df.info()
In [82]:
df.summary
Out[82]:
Таким простым вызовом мы получаем новый столбец с длинной строки описания товара, который может быть хорошим индикатором для вашей модели.
In [83]:
df.summary.str.len()
Out[83]:
In [13]:
# Your code here
Нижний регистр.
In [85]:
df.summary.str.lower()
Out[85]:
Верхний регистр.
In [15]:
df.summary.str.upper()
Out[15]:
Поиск строк, которые содержат определенную подстроку или regex
In [86]:
pattern = 'durable'
In [87]:
df.summary.str.contains(pattern)
Out[87]:
День недели
In [18]:
df.unixReviewTime.dt.dayofweek
Out[18]:
Неделя в году
In [19]:
df.unixReviewTime.dt.weekofyear
Out[19]:
In [ ]:
# ваш код
DataFrame имеет очень мощный функционал для поиска необходимых данных.
Таким простым вызовом мы можем выбрать индексы всех строк отзывов, у которых оценка ниже 5.
In [22]:
df.overall < 5
Out[22]:
Передав их как ключ, мы получим сами строки.
In [23]:
df[df.overall < 5]
Out[23]:
Полученные индексы мы можем передать в метод loc
, вторым аргументом он принимает список столбцов, которые мы хотим видеть.
In [24]:
df.loc[df.overall < 5, ['overall', 'reviewText']]
Out[24]:
Также мы можем передать более сложные условия для выборки, например, здесь мы выбираем отзывы с оценкой 5, содержащие слово awesome
и отзывы с оценкой 1, содержащие слово terrible
.
In [90]:
df.loc[((df.overall == 5) & (df.reviewText.str.contains('awesome'))) | ((df.overall == 1) & (df.reviewText.str.contains('terrible'))), ['overall', 'reviewText']]
Out[90]:
In [26]:
# Your code here
isin
работает по такому принцип: мы ему передаем набор значений, а он выбирает строки, которые им соответствуют.
In [108]:
# возвращает столбец, содержащий количество уникальных значений asin
products = df.asin.value_counts()
In [93]:
products
Out[93]:
In [106]:
products[0:3].index
Out[106]:
Выбираем строки, которые содержат топ 3 популярные товары.
In [107]:
df[df.asin.isin(products[0:3].index)]
# df[df.asin.isin(['B0000C321X', 'B0001ZNZJM', 'B00012O12A'])] - даст тот же результат
Out[107]:
In [109]:
# ваш код
In [32]:
days = df.unixReviewTime.value_counts()
In [33]:
days
Out[33]:
In [34]:
df[df.unixReviewTime.isin(days[0:1].index)]
Out[34]:
groupby работает по такому принципу:
df.groupby( grouper ).agg('mean')
In [110]:
df.groupby('asin')['reviewText'].agg('count').sort_values()
Out[110]:
In [111]:
# ваш код
In [114]:
# ваш код
Out[114]:
pd.Grouper
In [40]:
df.groupby([pd.Grouper(key='unixReviewTime',freq='D')])['reviewerID'].count()
Out[40]:
In [41]:
df.groupby([pd.Grouper(key='unixReviewTime',freq='M')])['reviewerID'].count()
Out[41]:
In [42]:
%matplotlib inline
import seaborn as sns; sns.set()
In [43]:
df.groupby([pd.Grouper(key='unixReviewTime',freq='A')])['reviewerID'].count().plot(figsize=(6,6))
Out[43]:
In [44]:
# Your code here
In [45]:
# Your code here
In [47]:
import matplotlib.pyplot as plt
by_weekday = df.groupby([df.unixReviewTime.dt.year,
df.unixReviewTime.dt.dayofweek]).mean()
by_weekday.columns.name = None # remove label for plot
fig, ax = plt.subplots(1, 2, figsize=(16, 6), sharey=True)
by_weekday.loc[2013].plot(title='Average Reviews Rating by Day of Week (2013)', ax=ax[0]);
by_weekday.loc[2014].plot(title='Average Reviews Rating by Day of Week (2014)', ax=ax[1]);
for axi in ax:
axi.set_xticklabels(['Mon', 'Tues', 'Wed', 'Thurs', 'Fri', 'Sat', 'Sun'])
In [50]:
import matplotlib.pyplot as plt
by_month = df.groupby([df.unixReviewTime.dt.year,
df.unixReviewTime.dt.day])['reviewerID'].count()
fig, ax = plt.subplots(1, 2, figsize=(16, 6), sharey=True)
by_month.loc[2012].plot(title='Average Reviews by Month (2012)', ax=ax[0]);
by_month.loc[2013].plot(title='Average Reviews by Month (2013)', ax=ax[1]);
Reading and writing data
pd.DataFrame()
pd.read_json()
pd.read_csv()
df.to_csv()
df.to_json()
...
Understading and formatting pandas data types
df.info()
df.to_datetime()
df.to_categoricals()
...
Working with text data
.str accessor
.str.len()
...
Working with timeseries data
.dt accessor
.str.dayofweek
...
Indexing
df.loc[]
df.iloc[]
.isin()
Grouping
df.groupby(grouper).agg('mean')
...