В таблице, которую мы рассматривали весь прошлый урок, каждый столбец сам по себе — вовсе не структура данных DataFrame. Удивлены? Давайте проверим. Таблица всё так же имеет тип DataFrame. image Но если мы возьмём отдельный столбец таблицы, то он представляет собой совсем иную структуру данных — Series. image Давайте разберёмся, что интересного в новом объекте Series. Series — одномерная таблица, и её элементы можно получить по индексу. Каждый индекс — это номер отдельного наблюдения, и поэтому несколько различных Series вместе составляют DataFrame. В Series хранятся данные одного типа. image У каждой Series есть имя (Name), информация о количестве данных в столбце (Length) и тип данных, которые хранятся в ней (dtype). print(df['Artist']) 0 Marina Rei 1 Stive Morgan 2 Stive Morgan 3 NaN 4 Rixton 5 Henry Hall & His Gleneagles Hotel Band 6 NaN 7 NaN 8 Andrew Paul Woodworth 9 Pillar Point 10 Steve Campbell 11 David Civera 12 Lumipa Beats 13 Henning Wehland 14 NaN 15 Пётр Каледин 16 ChinKong ... 67951 Julien Mier 67952 Bierstrassen Cowboys 67953 Flip Grater 67954 Alt & J 67955 TKN 67956 89ers 67957 Steel Pulse 67958 Nadine Coyle 67959 Digital Hero 67960 Red God 67961 Less Chapell 67962 NaN Name: Artist, Length: 67963, dtype: object Не все данные в этом столбце Artist относятся к типу object — есть и пропущенные значения NaN. О них мы подробно расскажем в теме, посвящённой «информационному мусору». Вместе с ними длина столбца равна общему числу наблюдений 67963. Индексация в Series аналогична индексации элементов столбца в DataFrame. Давайте рассмотрим на примере. Сохраним столбец total play в переменной total_play. total_play = df.loc[:, 'total play'] Для получения пятого по индексу элемента укажем 5 в квадратных скобках. print(total_play[5]) 3.007 Если надо получить диапазон ячеек, запросите атрибут loc с границами среза в квадратных скобках. print(total_play.loc[5:10]) 5 3.007 6 0.100 7 211.880 8 3.161 9 274.390 10 8.836 Name: total play, dtype: float64 Вот таблица различных вариантов индексации в Series с сокращённой записью. ВИД РЕАЛИЗАЦИЯ СОКРАЩЁННАЯ ЗАПИСЬ Один элемент total_play.loc[7] total_play[7] Несколько элементов total_play.loc[[5, 7, 10]] total_play[[5, 7, 10]] Несколько элементов подряд (срез) total_play.loc[5:10] включая 10 total_play[5:10] не включая 10 Все элементы, начиная с заданного total_play.loc[1:] total_play[1:] Все элементы до заданного total_play.loc[:3] включая 3 total_play[:3] не включая 3 Для Series также возможна логическая индексация. Рассмотрим такой пример — пользователю может не понравиться песня, которая начала играть, и он нажмёт кнопку «Следующий трек». Тогда в таблице сохраняется очень малое время прослушивания — от нуля до нескольких секунд. Вы можете проверить, сколько пользователей в течение нескольких секунд — не более 10 — приняли решение пропустить песню, которая только началась. Для решения задачи воспользуемся логическим условием total_play <= 10: image print(total_play.loc[total_play <= 10]) # выведем все элементы, которые удовлетворяют условию 3 8.966000 5 3.007000 6 0.100000 8 3.161000 10 8.836000 11 0.000000 13 2.000000 14 0.000000 15 0.000000 18 0.100000 19 7.000000 24 8.109446 26 0.000000 31 3.253000 33 0.100000 34 0.000000 36 9.200000 39 3.663453 40 0.100000 41 0.100000 42 1.464589 45 0.100000 47 0.100000 49 6.000000 51 0.872000 55 8.443000 63 1.687000 64 3.773000 66 7.670000 68 0.000000 ... 67878 0.919000 67880 1.090000 67885 2.000000 67886 4.040000 67887 7.680563 67888 8.578000 67894 2.065000 67896 0.000000 67897 0.100000 67899 3.676000 67900 0.000000 67905 0.000000 67906 3.682000 67907 4.179592 67908 0.000000 67912 0.000000 67916 6.947000 67917 4.000000 67918 0.000000 67923 1.753000 67927 1.954282 67929 0.100000 67932 1.439000 67946 2.101000 67949 0.100000 67950 3.496000 67951 1.318000 67953 2.502000 67956 2.000000 67962 0.100000 Name: total play, Length: 29160, dtype: float64 print(total_play.loc[total_play <= 10].count()) # посчитаем общее количество элементов, которые удовлетворяют условиям 29160 Порог в 10 секунд мы выбрали произвольно. Но было бы интересно установить, существует ли на самом деле какое-нибудь пороговое время — длительность воспроизведения композиции, после которого пользователь чаще всего не пропускает трек, а слушает его до конца. Анализ данных позволяет ставить такие задачи и находить на них ответы. Давайте вернёмся к войне между роком и попсой! Вам предлагается установить, сколько композиций этих жанров слушали не более 5 секунд и определить: зависит ли быстрота принятия решения о пропуске трека от жанра или на это влияют другие причины? TASK_1_7 Получите таблицу только с жанром rock и сохраните её в переменной rock. SOLUTION import pandas as pd df = pd.read_csv('music_log.csv') df['genre'] == 'rock' rock = df[df['genre'] == 'rock'] TASK_2_7 Выделим время прослушивания роковых композиций в особую структуру данных. Сохраните столбец 'total play' таблицы rock в переменной rock_time. SOLUTION import pandas as pd df = pd.read_csv('music_log.csv') df['genre'] == 'rock' rock = df[df['genre'] == 'rock'] # Выделим время прослушивания роковых композиций в особую структуру данных # Сохраним столбец 'total play' таблицы rock в переменной rock_time. rock_time = rock['total play'] TASK_3_7 Обратитесь к новой Series c именем rock_time и посчитайте количество треков жанра рок, пропущенных в течение 5 секунд. Логическим условием укажите rock_time <= 5. Результат сохраните в переменной rock_haters и напечатайте на экране с пояснением: Количество пропущенных треков жанра рок равно ... SOLUTION import pandas as pd df = pd.read_csv('music_log.csv') df['genre'] == 'rock' rock = df[df['genre'] == 'rock'] # Выделим время прослушивания роковых композиций в особую структуру данных # Сохраним столбец 'total play' таблицы rock в переменной rock_time. rock_time = rock['total play'] rock_haters=rock_time.loc[rock_time <= 5].count() print('Количество пропущенных треков жанра рок равно',rock_haters) TASK_4_7 Выберите из исходной таблицы только строки с жанром 'pop' и сохраните эту новую таблицу в переменной pop. Вывод результата предыдущей задачи закомментируйте. SOLUTION import pandas as pd df = pd.read_csv('music_log.csv') #df['genre'] == 'rock' #rock = df[df['genre'] == 'rock'] # Выделим время прослушивания роковых композиций в особую структуру данных # Сохраним столбец 'total play' таблицы rock в переменной rock_time. #rock_time = rock['total play'] #rock_haters=rock_time.loc[rock_time <= 5].count() #print('Количество пропущенных треков жанра рок равно',rock_haters) df['genre'] == 'pop' pop = df[df['genre'] == 'pop'] TASK_5_7 Теперь по аналогии с роком создайте Series, где хранятся только данные о времени воспроизведения композиций в жанре поп. Назовите его pop_time и сохраните в нём данные столбца 'total play' из таблицы pop . SOLUTION import pandas as pd df = pd.read_csv('music_log.csv') #df['genre'] == 'rock' #rock = df[df['genre'] == 'rock'] # Выделим время прослушивания роковых композиций в особую структуру данных # Сохраним столбец 'total play' таблицы rock в переменной rock_time. #rock_time = rock['total play'] #rock_haters=rock_time.loc[rock_time <= 5].count() #print('Количество пропущенных треков жанра рок равно',rock_haters) df['genre'] == 'pop' pop = df[df['genre'] == 'pop'] pop_time = pop['total play'] TASK_6_7 Снова по аналогии с роком обратитесь к Series, на сей раз pop_time, чтобы посчитать количество пропущенных в течение 5 секунд треков жанра поп. Используйте условие pop_time <= 5. Результат сохраните в переменной pop_haters и напечатайте на экране в таком виде: Количество пропущенных треков жанра поп равно ... Вывод данных о роке закомментируйте. SOLUTION import pandas as pd df = pd.read_csv('music_log.csv') #df['genre'] == 'rock' #rock = df[df['genre'] == 'rock'] # Выделим время прослушивания роковых композиций в особую структуру данных # Сохраним столбец 'total play' таблицы rock в переменной rock_time. #rock_time = rock['total play'] #rock_haters=rock_time.loc[rock_time <= 5].count() #print('Количество пропущенных треков жанра рок равно',rock_haters) df['genre'] == 'pop' pop = df.loc[df['genre'] == 'pop'] pop_time = pop['total play'] pop_haters=pop_time.loc[pop_time <= 5].count() print('Количество пропущенных треков жанра поп равно',pop_haters) TASK_7_7 Для обоих жанров посчитайте долю быстро пропущенных пользователями композиций в процентах. Разделите количество треков, которые пользователи пропустили — соответственно rock_haters и pop_haters — на общее количество треков жанра рок и жанра поп. Общее количество треков жанра равно количеству наблюдений в таблицах rock и pop, т.е. значению атрибута shape[0] этих таблиц. Результаты сохраните в переменных rock_skip и pop_skip. Выведите значения новых переменных в процентах с точностью до одного знака после запятой в такой форме: Доля пропущенных композиций жанра рок равна: ... Доля пропущенных композиций жанра поп равна: ... Вывод результата предыдущей задачи закомментируйте. SOLUTION import pandas as pd df = pd.read_csv('music_log.csv') # Получим таблицу только с жанром rock и сохраним её в переменной rock df['genre'] == 'rock' rock = df[df['genre'] == 'rock'] # Выделим время прослушивания роковых композиций в особую структуру данных # Сохраним столбец 'total play' таблицы rock в переменной rock_time. rock_time = rock['total play'] # Обратитмся к новой Series c именем rock_time и посчитайте количество треков жанра рок, пропущенных в течение 5 секунд. rock_haters = rock_time[rock_time <= 5].count() # print('Количество пропущенных треков жанра рок равно', rock_haters) # Выберем из исходной таблицы только строки с жанром 'pop' и сохраним эту новую таблицу в переменной pop. df['genre'] == 'pop' pop = df[df['genre'] == 'pop'] # Теперь по аналогии с роком создайте Series, где хранятся только данные о времени воспроизведения композиций в жанре поп. pop_time = pop['total play'] #Снова по аналогии с роком обратимся к Series, на сей раз pop_time, чтобы посчитать количество пропущенных в течение 5 секунд треков жанра поп. pop_haters = pop_time[pop_time <= 5].count() # print('Количество пропущенных треков жанра поп равно', pop_haters) # Для обоих жанров посчитайте долю быстро пропущенных пользователями композиций в процентах. df['genre'] == 'rock' rock = df[df['genre'] == 'rock'] rock_time = rock['total play'] rock_haters = rock_time[rock_time <= 5].count() df['genre'] == 'pop' pop = df[df['genre'] == 'pop'] pop_time = pop['total play'] pop_haters = pop_time[pop_time <= 5].count() rock_skip=rock_haters/rock.shape[0] print('Доля пропущенных композиций жанра рок равна: {:.1%}'.format(rock_skip)) pop_skip = pop_haters/pop.shape[0] print('Доля пропущенных композиций жанра поп равна: {:.1%}'.format(pop_skip))