test
/
Pandas_pr3.ipynb
974 строки · 35.0 Кб
1{
2"cells": [
3{
4"cell_type": "markdown",
5"metadata": {
6"id": "nPCp6G1zI-Ew"
7},
8"source": [
9"# Работа с Pandas\n",
10"\n",
11"\n",
12"## Series\n",
13"\n",
14"`Series` - это одна из структур данных библиотеки `pandas`. Она представляет собой что-то вроде словаря, однако, является упорядоченной.\n",
15"\n",
16"Создадим какой-нибудь список, а затем получим на его основе объект `Series`:"
17]
18},
19{
20"cell_type": "code",
21"execution_count": 1,
22"metadata": {
23"id": "UUMvqVhwI-Ex"
24},
25"outputs": [],
26"source": [
27"import pandas as pd"
28]
29},
30{
31"cell_type": "code",
32"execution_count": null,
33"metadata": {
34"id": "r7BIt-kQI-E1"
35},
36"outputs": [],
37"source": [
38"a = [1, 3, 5, 7, 2]\n",
39"\n",
40"b = pd.Series(a)\n",
41"\n",
42"print(b)"
43]
44},
45{
46"cell_type": "markdown",
47"metadata": {
48"id": "RNvSFF_NI-E6"
49},
50"source": [
51"В результате такой операции получается объект `Series`, содержащий элементы из списка `a`. Здесь справа располагаются элементы из `a`, а слева - их индексы. Поскольку индексы для этих элементов мы явно не указали, используются стандартные.\n",
52"\n",
53"Индексы можно также указать явно, для этого нужно подать в качестве аргумента `index` список из индексов. Данный список должен быть той же длины, что и список `a`.\n"
54]
55},
56{
57"cell_type": "markdown",
58"metadata": {
59"id": "akKQ3IiUI-FA"
60},
61"source": [
62"Индексы можно задать сразу, а можно и изменить позже:"
63]
64},
65{
66"cell_type": "code",
67"execution_count": null,
68"metadata": {
69"id": "ruk5GAE3I-FB"
70},
71"outputs": [],
72"source": [
73"b.index = [\"a\", \"b\", \"c\", \"d\", \"e\"]\n",
74"\n",
75"print(b)"
76]
77},
78{
79"cell_type": "markdown",
80"metadata": {
81"id": "YxxTvVIFI-FR"
82},
83"source": [
84"Индексы в `Series` не обязаны быть уникальными:"
85]
86},
87{
88"cell_type": "code",
89"execution_count": null,
90"metadata": {
91"id": "65AeCMUbI-FS"
92},
93"outputs": [],
94"source": [
95"d = pd.Series(a, index=[0, 1, 0, 1, 0])\n",
96"\n",
97"print(d)"
98]
99},
100{
101"cell_type": "markdown",
102"metadata": {
103"id": "G5Z7PCwmI-GK"
104},
105"source": [
106"### Добавление и удаление данных в Series\n",
107"\n",
108"С помощью метода `.append` мы можем добавлять к одному массиву `Series` другой:"
109]
110},
111{
112"cell_type": "code",
113"execution_count": null,
114"metadata": {
115"id": "sHq5bhAII-GL"
116},
117"outputs": [],
118"source": [
119"g = d.append(b)\n",
120"\n",
121"print(g)"
122]
123},
124{
125"cell_type": "markdown",
126"metadata": {
127"id": "1OnEv778I-GO"
128},
129"source": [
130"С помощью метода `.drop` мы можем удалять из массива элементы с определёнными индексами. Эти индексы мы и подаём в метод в виде списка:"
131]
132},
133{
134"cell_type": "code",
135"execution_count": null,
136"metadata": {
137"id": "n_TqKZG_I-GP"
138},
139"outputs": [],
140"source": [
141"h = g.drop([0, \"d\"])\n",
142"\n",
143"print(h)"
144]
145},
146{
147"cell_type": "markdown",
148"metadata": {
149"id": "B9GSACSLI-GR"
150},
151"source": [
152"Обратите внимание, что эти методы, в отличие от аналогичных методов из стандартных библиотек питона, не изменяют исходный массив, но возвращают новый.\n",
153"\n",
154"### Запись и чтение массивов Series из файла\n",
155"\n",
156"\n",
157"Для записи массивов `Series` в файлы используется формат файлов под названием `pickle`. Этот формат позволяет полностью сохранять питоновские объекты, а затем загружать их в неизменном виде.\n",
158"\n",
159"Для записи массива `Series` в файл используется метод `.to_pickle`, а для чтения - функция `np.read_pickle`:"
160]
161},
162{
163"cell_type": "code",
164"execution_count": 13,
165"metadata": {
166"id": "ZTrPh3ELI-GS"
167},
168"outputs": [],
169"source": [
170"h.to_pickle(\"h.pkl\")"
171]
172},
173{
174"cell_type": "code",
175"execution_count": null,
176"metadata": {
177"id": "ZYirazZHI-GV"
178},
179"outputs": [],
180"source": [
181"h1 = pd.read_pickle(\"h.pkl\")\n",
182"\n",
183"print(h1)"
184]
185},
186{
187"cell_type": "markdown",
188"metadata": {
189"id": "VtiWsjwkI-GX"
190},
191"source": [
192"## DataFrame\n",
193"\n",
194"`DataFrame` - двумерная структура данных из библиотеки `pandas`, позволяющая удобно работать с таблицами.\n",
195"\n",
196"Самый простой способ задать `DataFrame` - с помощью словаря, в котором каждый ключ отвечает за столбец, а соответствующее значение - это список из элементов данного столбца. Эти списки должны иметь одинаковую длину."
197]
198},
199{
200"cell_type": "code",
201"execution_count": null,
202"metadata": {
203"id": "Do-NbZz3I-GY"
204},
205"outputs": [],
206"source": [
207"a = {\n",
208" \"col1\": [1, 2, 4, 5, 6, 7, 8],\n",
209" \"col2\": [\"a\", \"c\", \"e\", \"g\", \"z\", \"x\", \"y\"]\n",
210"}\n",
211"\n",
212"b = pd.DataFrame(a)\n",
213"\n",
214"b"
215]
216},
217{
218"cell_type": "markdown",
219"metadata": {
220"id": "5r6rUlqxI-Gb"
221},
222"source": [
223"С помощью атрибута `.shape` можно посмотреть форму массива `DataFrame`. Атрибут `.columns` содержит массив из столбцов, а `.index`, как и ранее, содержит массив индексов."
224]
225},
226{
227"cell_type": "code",
228"execution_count": null,
229"metadata": {
230"id": "d-BlBVFnI-Gc"
231},
232"outputs": [],
233"source": [
234"print(\"Форма b: {}\".format(b.shape))\n",
235"\n",
236"print(\"Столбцы b: {}\".format(b.columns))\n",
237"\n",
238"print(\"Индексы b: {}\".format(b.index))"
239]
240},
241{
242"cell_type": "markdown",
243"metadata": {
244"id": "pgn1tqBbI-Gf"
245},
246"source": [
247"Общую информацию о массиве можно запросить с помощью метода `.info`. Нам вернётся информация об индексах и столбцах данного массива, о том, какие типы данных хранятся в каждом из столбцов, а также информация о том, сколько памяти выделено под данный массив."
248]
249},
250{
251"cell_type": "code",
252"execution_count": null,
253"metadata": {
254"id": "6kE3cFoPI-Gg"
255},
256"outputs": [],
257"source": [
258"b.info()"
259]
260},
261{
262"cell_type": "markdown",
263"metadata": {
264"id": "IKpjQKm0I-Gj"
265},
266"source": [
267"С помощью метода `.describe` можно получить некоторые статистические характеристики по столбцам с числовыми значениями: среднее значение, среднее квадратическое отклонение, максимум, минимум, квантили и пр."
268]
269},
270{
271"cell_type": "code",
272"execution_count": null,
273"metadata": {
274"id": "pDzeYsuQI-Gj"
275},
276"outputs": [],
277"source": [
278"b.describe()"
279]
280},
281{
282"cell_type": "markdown",
283"metadata": {
284"id": "F4El81QKI-HS"
285},
286"source": [
287"### Случайный выбор значений из DataFrame\n",
288"\n",
289"Случайный выбор строк из массива `DataFrame` производится с помощью метода `.sample`. Вот несколько его важных параметров:\n",
290"\n",
291"* `frac` - какую долю от общего числа строк нужно вернуть (число от 0 до 1)\n",
292"* `n` - сколько строк нужно вернуть (число от 0 до числа строк в массиве)\n",
293"* `replace` - индикатор того, производится ли выбор _с возвращением_, т.е. с возможным повторением строк в выборке, или _без возвращения_ (`True` или `False`)\n",
294"\n",
295"Нельзя использовать параметры `frac` и `n` одновременно, нужно выбрать какой-то один."
296]
297},
298{
299"cell_type": "code",
300"execution_count": null,
301"metadata": {
302"id": "U2roX2B-I-HT"
303},
304"outputs": [],
305"source": [
306"b.sample(frac=0.5, replace=True)"
307]
308},
309{
310"cell_type": "markdown",
311"metadata": {
312"id": "FsUnA0MdI-HZ"
313},
314"source": [
315"Если требуется просто перемешать всю выборку, это также можно выполнить с помощью метода `.sample`, передав в него параметр `frac=1`.\n",
316"\n",
317"### Запись и чтение DataFrame из файлов\n",
318"\n",
319"Для хранения таблиц широко распространён формат файлов с расширением `.csv`.\n",
320"\n",
321"Сохранить массив в файл можно с помощью метода `.to_csv`. Вот несколько важных параметров этого метода:\n",
322"\n",
323"* `sep` - символ, который нужно использовать для разделения значения столбцов между собой. По умолчанию это `\",\"`, но можно также использовать `\";\"`, `\"\\t\"` и др.\n",
324"* `index` - булево значение, индикатор того, нужно ли в файл сохранить также столбец индексов.\n"
325]
326},
327{
328"cell_type": "code",
329"execution_count": 20,
330"metadata": {
331"id": "RYMORR5TI-Hb"
332},
333"outputs": [],
334"source": [
335"b.to_csv(\"test.csv\", sep=\";\", index=False)"
336]
337},
338{
339"cell_type": "markdown",
340"metadata": {
341"id": "IyBxeXaVI-Hm"
342},
343"source": [
344"Прочитать массив из файла можно с помощью функции `pd.read_csv`. Здесь также можно указать разделитель столбцов в параметре `sep`."
345]
346},
347{
348"cell_type": "code",
349"execution_count": null,
350"metadata": {
351"id": "Lk_wWrT2I-Hm"
352},
353"outputs": [],
354"source": [
355"b1 = pd.read_csv(\"test.csv\", sep=\";\")\n",
356"\n",
357"b1"
358]
359},
360{
361"cell_type": "markdown",
362"metadata": {
363"id": "eFmm9O6UI-Hp"
364},
365"source": [
366"У данных команд для сохранения и чтения таблиц есть множество других важных и полезных параметров, поэтому рекомендуется также изучить их документацию: [to_csv](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.to_csv.html), [read_csv](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_csv.html).\n",
367"\n",
368"В `pandas` также имеются аналогичные команды для сохранения и записи таблиц как `excel` и `pickle`."
369]
370},
371{
372"cell_type": "markdown",
373"metadata": {
374"id": "yiL5JLa-I-Hp"
375},
376"source": [
377"## Работа с данными в Pandas\n",
378"\n",
379"### Слияние данных\n",
380"\n",
381"Рассмотрим следующий пример. Допустим, что мы работаем с небольшим отделом книжного магазина, в котором продаётся классическая литература. Наша задача - систематизировать ассортимент отдела.\n",
382"\n",
383"У нас есть таблица `authors`, содержащая данные об авторах: их идентификаторы (`author_id`) и имена (`author_name`):"
384]
385},
386{
387"cell_type": "code",
388"execution_count": null,
389"metadata": {
390"id": "ol2u5eVDI-Hq"
391},
392"outputs": [],
393"source": [
394"authors = pd.DataFrame({\n",
395" 'author_id': [1, 2, 3],\n",
396" 'author_name': ['Пушкин', 'Толстой', 'Достоевский'],\n",
397"})\n",
398"\n",
399"authors"
400]
401},
402{
403"cell_type": "markdown",
404"metadata": {
405"id": "6-IVLnBvI-Hs"
406},
407"source": [
408"Кроме того, у нас есть таблица `books`, содержащая информацию о книгах этих авторов. В этой таблице также есть колонка `author_id`, а также колонка `book_title`, содержащая название книги:"
409]
410},
411{
412"cell_type": "code",
413"execution_count": null,
414"metadata": {
415"id": "ESCfC0eaI-Hs"
416},
417"outputs": [],
418"source": [
419"books = pd.DataFrame({\n",
420" 'author_id': [2, 3, 3, 4],\n",
421" 'book_title': ['Война и мир', 'Идиот', 'Преступление и наказание',\n",
422" 'Отцы и дети'],\n",
423"})\n",
424"\n",
425"books"
426]
427},
428{
429"cell_type": "markdown",
430"metadata": {
431"id": "YrsRPVSEI-Hv"
432},
433"source": [
434"Что делать, если мы, например, захотим сопоставить названия книг именам их авторов? Для этого используется функция `pd.merge`: в эту функцию помещаются те таблицы, которые мы хотим соединить, а также несколько других важных аргументов:\n",
435"\n",
436"* `on` - параметр, отвечающий за то, какой столбец мы будем использовать для слияния,\n",
437"* `how` - каким образом производить слияние.\n",
438"\n",
439"Опишем подробнее, какие значения может принимать параметр `how`:\n",
440"\n",
441"* `\"inner\"` - внутреннее слияние. В этом случае в слиянии участвуют только те строки, которые присутствуют в обоих таблицах,\n",
442"* `\"left\"` - в слиянии участвуют все строки из левой таблицы,\n",
443"* `\"right\"` - то же самое, но для правой таблицы,\n",
444"* `\"outer\"` - внешнее слияние, соединяются все строки как из левой, так и из правой таблицы."
445]
446},
447{
448"cell_type": "code",
449"execution_count": null,
450"metadata": {
451"id": "8n2gin-nI-Hw"
452},
453"outputs": [],
454"source": [
455"pd.merge(authors, books, on='author_id', how='inner')"
456]
457},
458{
459"cell_type": "markdown",
460"metadata": {
461"id": "bVPmcn37I-Hy"
462},
463"source": [
464"Если мы выбираем `\"left\"`, `\"right\"` или `\"outer\"`, может случиться так, что строку из одной таблицы будет невозможно соединить со второй. Например, мы видим, что в нашей таблице `books` нет произведений Пушкина (его `id` равен 1). В свою очередь, в таблице `books` есть книга, для которой `author_id` равен 4, хотя, в таблице `authors` нет записи с таким `author_id`. Рассмотрим внешнее слияние этих таблиц:"
465]
466},
467{
468"cell_type": "code",
469"execution_count": null,
470"metadata": {
471"id": "P9E4mInBI-Hz"
472},
473"outputs": [],
474"source": [
475"merged_df = pd.merge(authors, books, on='author_id', how='outer')\n",
476"\n",
477"merged_df"
478]
479},
480{
481"cell_type": "markdown",
482"metadata": {
483"id": "Af0I2qVKI-H3"
484},
485"source": [
486"Как мы видим, в получившейся таблице присутствуют пропущенные значения (`NaN`).\n",
487"\n",
488"### Работа с пропущенными данными\n",
489"\n",
490"Пропущенные значения в `Series` или `DataFrame` можно получить с помощью метода `.isnull`. Наоборот, все имеющиеся непустые значения можно получить с помощью метода `.notnull`:"
491]
492},
493{
494"cell_type": "code",
495"execution_count": null,
496"metadata": {
497"id": "PIVEZX7sI-H3"
498},
499"outputs": [],
500"source": [
501"merged_df[merged_df[\"author_name\"].isnull()]"
502]
503},
504{
505"cell_type": "code",
506"execution_count": null,
507"metadata": {
508"id": "F0MaLqu1I-H5"
509},
510"outputs": [],
511"source": [
512"merged_df[merged_df[\"author_name\"].notnull()]"
513]
514},
515{
516"cell_type": "markdown",
517"metadata": {
518"id": "pNq0X7x-I-H7"
519},
520"source": [
521"Заполнить пропущенные значения каким-то своим значением можно с помощью метода `.fillna()`:"
522]
523},
524{
525"cell_type": "code",
526"execution_count": null,
527"metadata": {
528"id": "76FEe8XjI-H8"
529},
530"outputs": [],
531"source": [
532"merged_df[\"author_name\"] = merged_df[\"author_name\"].fillna(\"unknown\")\n",
533"\n",
534"merged_df"
535]
536},
537{
538"cell_type": "markdown",
539"metadata": {
540"id": "nVrQXD-II-H-"
541},
542"source": [
543"### Добавление столбцов в `DataFrame`.\n",
544"\n",
545"Допустим, каждая из наших книг имеется в единственном экземпляре. Мы хотели бы создать в таблице `merged_df` столбец `quantity`, который бы содержал количество экземпляров каждой книги.\n",
546"\n",
547"Создание нового столбца в таблице `DataFrame` происходит аналогично созданию нового значения в словаре `dict`. Достаточно просто объявить значение `merged_df[\"quantity\"]`. Если подать в это значение какое-нибудь число или строку, то все значения в данном столбце приравняются к этому числу или строке. Также можно подать сюда список, тогда значения из этого списка поступят в соответствующие строки этого столбца. В этом случае длина списка обязана совпадать с числом строк таблицы.\n",
548"\n",
549"Итак, выберем все строки с непустым значением поля `book_title`, и для них запишем в столбец `quantity` число 1. Это можно сделать с помощью атрибута `.loc`:"
550]
551},
552{
553"cell_type": "code",
554"execution_count": null,
555"metadata": {
556"id": "qMczv7OTI-H-"
557},
558"outputs": [],
559"source": [
560"merged_df.loc[merged_df[\"book_title\"].notnull(), \"quantity\"] = 1\n",
561"\n",
562"merged_df"
563]
564},
565{
566"cell_type": "markdown",
567"metadata": {
568"id": "AOBt9xicI-IA"
569},
570"source": [
571"Теперь заполним все пропуски в этом столбце числом 0:"
572]
573},
574{
575"cell_type": "code",
576"execution_count": null,
577"metadata": {
578"id": "lPJUXA6-I-IB"
579},
580"outputs": [],
581"source": [
582"merged_df[\"quantity\"].fillna(0, inplace=True)\n",
583"\n",
584"merged_df"
585]
586},
587{
588"cell_type": "markdown",
589"metadata": {
590"id": "y9n61GsAI-ID"
591},
592"source": [
593"Наконец, приведём значения в этом столбце к типу `int`. (Это сделать невозможно, если в столбце содержатся пропуски.)"
594]
595},
596{
597"cell_type": "code",
598"execution_count": null,
599"metadata": {
600"id": "oiC1eYVvI-IE"
601},
602"outputs": [],
603"source": [
604"merged_df[\"quantity\"] = merged_df[\"quantity\"].astype(int)\n",
605"\n",
606"merged_df"
607]
608},
609{
610"cell_type": "markdown",
611"metadata": {
612"id": "S4WgroS-I-IG"
613},
614"source": [
615"В `DataFrame` можно использовать индексы по умолчанию, а можно и назначить свои. Например, в качестве индексов можно использовать какой-нибудь из столбцов:"
616]
617},
618{
619"cell_type": "code",
620"execution_count": null,
621"metadata": {
622"id": "VfSnwKwsI-IG"
623},
624"outputs": [],
625"source": [
626"merged_df.set_index(\"author_id\", inplace=True)\n",
627"\n",
628"merged_df"
629]
630},
631{
632"cell_type": "markdown",
633"metadata": {
634"id": "a3YQjgpMI-II"
635},
636"source": [
637"Если что, индексы всегда можно сбросить. Тогда текущие индексы становятся столбцом:"
638]
639},
640{
641"cell_type": "code",
642"execution_count": null,
643"metadata": {
644"id": "5aABCnNqI-IJ"
645},
646"outputs": [],
647"source": [
648"merged_df.reset_index(inplace=True)\n",
649"\n",
650"merged_df"
651]
652},
653{
654"cell_type": "markdown",
655"metadata": {
656"id": "jMLzx0I7I-IN"
657},
658"source": [
659"### Удаление данных\n",
660"\n",
661"Для удаления данных из `DataFrame` используется метод `.drop`. В этот метод подаётся метка элемента, который необходимо удалить (индекс строки или название столбца), а также ось `axis`. При `axis=0` удаляется строка, при значении `axis=1` - столбец:"
662]
663},
664{
665"cell_type": "code",
666"execution_count": null,
667"metadata": {
668"id": "akegn7sVI-IO"
669},
670"outputs": [],
671"source": [
672"merged_df[\"price\"] = 500\n",
673"\n",
674"merged_df"
675]
676},
677{
678"cell_type": "code",
679"execution_count": null,
680"metadata": {
681"id": "Iycv-BFlI-IT"
682},
683"outputs": [],
684"source": [
685"merged_df.drop(\"price\", axis=1, inplace=True)\n",
686"\n",
687"merged_df"
688]
689},
690{
691"cell_type": "markdown",
692"metadata": {
693"id": "6iF3MhWUI-IW"
694},
695"source": [
696"Теперь удалим строку с индексом 1:"
697]
698},
699{
700"cell_type": "code",
701"execution_count": null,
702"metadata": {
703"id": "XbMgSWZ_I-IX"
704},
705"outputs": [],
706"source": [
707"merged_df.drop(1, axis=0, inplace=True)\n",
708"\n",
709"merged_df"
710]
711},
712{
713"cell_type": "markdown",
714"metadata": {
715"id": "cHSeORq8I-IY"
716},
717"source": [
718"### Сортировка данных\n",
719"\n",
720"Вернём только что удалённую строку. Напомним, что для этого используется метод `.append`. Кстати, добавлять строки к `DataFrame` можно прямо в виде словарей `dict`:"
721]
722},
723{
724"cell_type": "code",
725"execution_count": null,
726"metadata": {
727"id": "1GbbSJHeI-Ia"
728},
729"outputs": [],
730"source": [
731"merged_df = merged_df.append(\n",
732" {\n",
733" \"author_id\": 2,\n",
734" \"author_name\": \"Толстой\",\n",
735" \"book_title\": \"Война и мир\",\n",
736" \"quantity\": 1,\n",
737" },\n",
738" ignore_index=True,\n",
739")\n",
740"\n",
741"merged_df"
742]
743},
744{
745"cell_type": "markdown",
746"metadata": {
747"id": "jnJVEYYJI-Ih"
748},
749"source": [
750"Параметр `ignore_index=True` подаётся сюда, чтобы индексы соединяемых таблиц не учитывались. В результирующей таблице будут использованы стандартные последовательные индексы, начинающиеся с 0.\n",
751"\n",
752"Отсортируем эту таблицу по столбцу `author_id`. Это делается с помощью метода `.sort_values`:"
753]
754},
755{
756"cell_type": "code",
757"execution_count": null,
758"metadata": {
759"id": "WlwQC7ZgI-Ih"
760},
761"outputs": [],
762"source": [
763"merged_df.sort_values(by=\"author_id\", inplace=True)\n",
764"\n",
765"merged_df"
766]
767},
768{
769"cell_type": "markdown",
770"metadata": {
771"id": "gKydz8lII-Ij"
772},
773"source": [
774"Чтобы сбросить индексы, воспользуемся уже известным методом `.reset_index`. В нашем случае, стоит подать в него аргумент `drop=True`, который означает, что текущий столбец из индексов не нужно сохранять в таблице, а можно удалить."
775]
776},
777{
778"cell_type": "code",
779"execution_count": null,
780"metadata": {
781"id": "FvYreG9bI-Ij"
782},
783"outputs": [],
784"source": [
785"merged_df.reset_index(drop=True, inplace=True)\n",
786"\n",
787"merged_df"
788]
789},
790{
791"cell_type": "markdown",
792"metadata": {
793"id": "dfIIi0LGI-Im"
794},
795"source": [
796"### Соединение таблиц\n",
797"\n",
798"Для соединения таблиц можно пользоваться функцией `pd.concat`. С этой функцией мы уже знакомились, когда изучали библиотеку `numpy`. Здесь эта функция работает аналогичным образом: соединяет таблицы либо вертикально (если указан параметр `axis=0`), либо горизонтально (если `axis=1`).\n",
799"\n",
800"Соединение происходит с сохранением индексов, если не указан параметр `ignore_index=True`."
801]
802},
803{
804"cell_type": "code",
805"execution_count": null,
806"metadata": {
807"id": "Jc68kpVPI-Im"
808},
809"outputs": [],
810"source": [
811"df1 = pd.DataFrame({\n",
812" 'author_id': [3, 5],\n",
813" 'author_name': ['Достоевский', 'Чехов'],\n",
814" 'book_title': ['Бесы', 'Три сестры'],\n",
815" 'quantity': [2, 3],\n",
816"})\n",
817"\n",
818"df2 = pd.concat([merged_df, df1], axis=0, ignore_index=True)\n",
819"\n",
820"df2"
821]
822},
823{
824"cell_type": "code",
825"execution_count": null,
826"metadata": {
827"id": "G06O6mgeI-Iq"
828},
829"outputs": [],
830"source": [
831"df3 = pd.DataFrame(\n",
832" {'price': [700, 450, 500, 400, 350]},\n",
833" index=[1, 2, 3, 5, 6],\n",
834")\n",
835"\n",
836"df4 = pd.concat([df2, df3], axis=1)\n",
837"\n",
838"df4"
839]
840},
841{
842"cell_type": "markdown",
843"metadata": {
844"id": "g7uNIdjiI-Ir"
845},
846"source": [
847"### Операции над таблицами\n",
848"\n",
849"Как и ранее с массивами `numpy` и `Series`, с таблицами `DataFrame` можно производить различные математические операции. Например, значения различных столбцов можно поэлементно перемножать, складывать и пр."
850]
851},
852{
853"cell_type": "code",
854"execution_count": null,
855"metadata": {
856"id": "5e-ebivAI-Ir"
857},
858"outputs": [],
859"source": [
860"df4[\"total\"] = df4[\"quantity\"] * df4[\"price\"]\n",
861"\n",
862"df4"
863]
864},
865{
866"cell_type": "markdown",
867"metadata": {
868"id": "NTI-BTHbI-It"
869},
870"source": [
871"С помощью метода `.nlargest` можно вывести несколько наибольших значений. Указывается то, сколько значений нужно вернуть, а также то, по какому именно значению нужно сортировать:"
872]
873},
874{
875"cell_type": "code",
876"execution_count": null,
877"metadata": {
878"id": "qzIHHkGQI-It"
879},
880"outputs": [],
881"source": [
882"df4.nlargest(3, \"price\")"
883]
884},
885{
886"cell_type": "markdown",
887"metadata": {
888"id": "iTygSn5hI-Iv"
889},
890"source": [
891"Имеется также аналогичный метод `.nsmallest`."
892]
893},
894{
895"cell_type": "markdown",
896"metadata": {
897"id": "rbPPZVFVI-I2"
898},
899"source": [
900"### Группировка данных\n",
901"\n",
902"Данные в таблице `DataFrame` можно группировать по повторяющимся значениям выбранного столбца. Группировка позволяет вычислять какие-то _агренированные_ значения, т.е. значения, полученные каким-то образом из групп других значений. Например, если мы захотим сгруппировать нашу таблицу по значениям `author_name`, то каждая группа будет содержать все строки с одинаковым значением `author_name`. По таким группам можно затем посчитать какую-нибудь агрегирующую функцию, например, сумму, среднее, минимум и др.\n",
903"\n",
904"Вот несколько способов это сделать. В первом случае мы просто выбираем конкретный столбец из группировки и применяем к нему какую-то агрегирующую функцию:"
905]
906},
907{
908"cell_type": "code",
909"execution_count": 45,
910"metadata": {
911"id": "2VTGNpTMI-I2"
912},
913"outputs": [],
914"source": [
915"groupby = df4.groupby(\"author_name\")"
916]
917},
918{
919"cell_type": "code",
920"execution_count": null,
921"metadata": {
922"id": "T1UW_htmI-I3"
923},
924"outputs": [],
925"source": [
926"groupby[\"price\"].mean()"
927]
928},
929{
930"cell_type": "markdown",
931"metadata": {
932"id": "hkYvCWkBI-I5"
933},
934"source": [
935"Второй способ - с помощью метода `.agg`. Данный метод является более гибким. Например, он позволяет вычислять одновременно несколько различных агрегирующих функций от разных столбцов:"
936]
937},
938{
939"cell_type": "code",
940"execution_count": null,
941"metadata": {
942"id": "gTWXVizZI-I5"
943},
944"outputs": [],
945"source": [
946"groupby.agg({\"price\": \"max\", \"total\": \"count\"})"
947]
948}
949],
950"metadata": {
951"colab": {
952"provenance": []
953},
954"kernelspec": {
955"display_name": "Python 3",
956"language": "python",
957"name": "python3"
958},
959"language_info": {
960"codemirror_mode": {
961"name": "ipython",
962"version": 3
963},
964"file_extension": ".py",
965"mimetype": "text/x-python",
966"name": "python",
967"nbconvert_exporter": "python",
968"pygments_lexer": "ipython3",
969"version": "3.7.4"
970}
971},
972"nbformat": 4,
973"nbformat_minor": 0
974}