Pull to refresh

Comments 8

Мда. Даже у джуна DS все это уже на подкорке записано. Представить, что при обработке нужно смотреть не в pandas.pydata.org, а в шпаргалку, вы уж простите меня великодушно, не могу.
Про пункт «Подсчёт количества уникальных значений в столбце»: можно это сделать без len(), с помощью метода nunique().
В остальном, спасибо за шпаргалку!
len(ratings['user_id'].unique())

А можно и просто: ratings['user_id'].nunique()
anime.type.value_counts()

Лучше использовать вариант с обращением к имени колонки через[]: anime['type'].value_counts()
На 100% согласен. [anime[column].some_func() for column in anime.columns] слишком часто используемая конструкция чтобы ею пренебрегать.
Хотя если кто то подскажет как в этом anime.type.value_counts() случае перебрать все столбцы буду благодарен!
Вместо len(), я бы использовал аттрибут .shape (возвращает tuple — rows, columns) — поэтому аналог будет .shape[0].
Эту конструкцию:
tmp_df = tmp_df[tmp_df.user_id < 10]
tmp_df = tmp_df[tmp_df.anime_id < 30]
tmp_df = tmp_df[tmp_df.rating != -1]
можно заменить на фильтр И:
tmp_df[(tmp_df.user_id < 10) & (tmp_df.anime_id < 30) & (tmp_df.rating != -1)]
мне (как новичку) понравилось. удобно и понятно, спасибо за такую шпаргалку.
и классная фраза в преамбуле)
Вспоминаем Zen Of Python (Explicit is better than implicit) и вместо тормозных неявных срезов вида «anime[1:3]» и «anime[anime['rating'] > 8]» всегда используем очевидные и явные loc/iloc.

Поясню: в целях удобства записи одноразовых вычислений pandas API написан с использованием перекрытых операторов индекса, но они могут в некоторых случаях затыкаться или извлекать не то, что хотелось бы. С loc/iloc pandas-у нет нужды пытаться угадать, что вы имели в виду.

На самом деле нужда всё равно останется, сейчас объясню, почему :)

Проанализируем выражение «anime[anime['rating'] > 8]», которое примерно равнозначно нижеследующему:

bool_index_mask = anime['rating'] > 8
result = anime[bool_index_mask]
del bool_mask
return result

Мы уже знаем, что неявную индексацию в обоих случаях [] лучше бы заменить на .loc[]/.iloc[]

Но как бедному пандасу прикажете угадать, что вы имели в виду в выражении фильтра: anime.loc[:, 'rating'] > 8 или anime.loc[:, ['rating']] > 8? В первом случае сравнивается Series, во втором — DataFrame. Результатом будет в обоих случаях булевская маска, а Series работает быстрее и кушает меньше памяти, но питон не настолько умён, чтобы угадать, что лучше бы использовать Series.

Можно сделать запись ещё более явной и ещё немного ускорить создание маски: написать anime.loc[:, 'rating'].values > 8, но это уже на любителя

Если вам надо просто посчитать единственное значение в массиве из 10 строк, то, конечно, нет нужды заморачиваться с loc/iloc/values. Но если пишете прогу для больших данных, то пишите уж лучше явно, если не хотите потом искать по всему тексту, откуда у вас глюки лезут. Да, это чуть длиннее, но оно того стоит. И память, знаете ли, не резиновая, а процессоры не терагерцовые, так что лучше использовать более быстрые и компактные структуры
anime[anime['type'].isin(['TV', 'Movie'])]

Здесь лучше бы проще:


anime['type'].loc[['TV', 'Movie']]

tmp_df = tmp_df[tmp_df.user_id < 10] 
tmp_df = tmp_df[tmp_df.anime_id < 30] 
tmp_df = tmp_df[tmp_df.rating != -1]

Вот нагородил! Отчего бы не


tmp_df = tmp_df.query('user_id < 10 & anime_id < 30 & rating != -1')
Sign up to leave a comment.