Панды, чтобы найти самую симпатичную кошку в городе

Интересное введение в Pandas - библиотеку анализа данных Python

Привет, в прошлой статье мы рассмотрели решение типичного наибольшего числа n на группу с помощью SQL и Elasticsearch. В этой статье будет рассмотрено, как решить эту проблему с помощью мощной библиотеки анализа данных Python Pandas. 🐼

Pandas получил две важные структуры данных Series и DataFrame. Мы будем исследовать структуру данных Pandas DataFrame и некоторые из ее функций, чтобы решить нашу проблему. Что касается проблемы, позвольте мне объяснить ее, если вы не читали предыдущую статью. В городе было бы много милых кошек. Нам нужно выбрать только по одному симпатичному котику из каждого города, которого зовут Мяу (или похожее на Мяу, увидим позже).

Если вы хотите продолжить, я предлагаю обратиться к официальному сайту Pandas для локальной настройки, или вы можете создать новый блокнот на Kaggle. И даже представить свое решение для Kaggle Finding Meow Task.

Давайте возьмем небольшой набор данных о кошках с идентификатором столбца, именем кошки, городом и уровнем привлекательности в диапазоне от 1 до 10, причем 10 - самый симпатичный.

Ожидаемый результат для этого набора данных:

Для начала мы импортируем библиотеку pandas как pd и создаем DataFrame df с образцом набора данных. Есть много способов создать DataFrame. Ниже я привел три варианта. Вариант 1 по словарю; вариант 2, загрузив локально доступный файл CSV; вариант 3: чтение CSV-файла по URL-адресу.

Создав DataFrame, вы можете использовать метод df.head() для получения первых 5 строк из DataFrame. При желании вы можете передать количество строк для извлечения, например df.head(10), получить первые 10 строк.

Подобно методу df.head(n), есть df.tail(n) для возврата последних n записей.

df.columns вернет все имена столбцов.
df.shape вернет кортеж, представляющий размерность DataFrame. Как и для нашего DataFrame, (10, 4), что означает 10 строк и 4 столбца.
df.size возвращает int, представляющий количество элементов в этом объекте. Как и в нашем DataFrame, 40 (10 * 4)

Чтобы получить краткое описание DataFrame, мы можем использовать df.info(). Наши данные содержат 4 ненулевых столбца по 10 записей в каждом. id и cuteness как int64 тип данных, что означает число. name и town как object. Это может быть полезной информацией, если вы имеете дело с неизвестными данными.

Если df.info предоставляет информацию о типе данных, использовании памяти и т. Д., Мы можем использовать df.describe() для получения статистических данных. Вы можете обратиться к официальным документам, чтобы понять, что означает каждое из этих чисел.

Чтобы обратиться к данным определенного столбца, вы можете получить доступ, например, df['town'], и выполнить по ним запросы. Чтобы получить уникальные значения для города столбца, мы можем запуститьdf['town'].unique(). Или, чтобы получить количество значений для каждого города, df['town'].value_counts(). По нашим данным, у нас 4 кошки в Дели, по 2 кошки в Мумбаи, Бангалоре и Мееруте, из которых нам нужно найти по 1 самой симпатичной кошке в каждом городе.

Чтобы увидеть максимальное значение для каждого столбца на город, мы можем сгруппировать данные по городам и использовать функцию max. Если вы посмотрите на результат ниже, на первый взгляд он может показаться решением нашей проблемы (игнорирование условия имени), но это определенно не так. Как я сказал ранее, он возвращает максимальное значение каждого столбца отдельно. Как видите, у нас нет записи с идентификатором и именем 5 и томом с симпатичностью как 10. Хотя у нас есть 8 в качестве максимального идентификатора в городе Бангалор. Точно так же 9 - максимальная привлекательность в Мируте и Мумбаи.

Чтобы найти кошек с кличкой мяу, мы должны добавить для этого фильтр. Есть несколько способов запроса данных. Как df[df['name']=='meow'] или выполнить строковый запрос, используя df.query(). В этой статье мы будем использовать предыдущую. Но могут быть некоторые сценарии, в которых последний более полезен, например, если вы получаете эти запросы из какого-либо внешнего источника.

Согласно нашей задаче, мы ищем не только кошачье имя «мяу», но даже то, которое звучит похоже. Таким образом, мы изменим наш поисковый запрос, чтобы также искать имена, содержащие мяу. Как мы это сделаем, превратим столбец в строку с помощью .str и воспользуемся методом contains для String. Посмотрите на результат поискового запроса ниже, теперь у нас есть подмножество кошек с кличкой мяу или похожей на нее.

С подмножеством кошек давайте сгруппируем их по городам и найдем максимальную привлекательность для каждого города. Это дает нам максимальную привлекательность для каждого города, но мы не определили кошек по этому результату. Мы потеряли несколько столбцов, таких как id и name.

Таким образом, вместо того, чтобы извлекать столбец привлекательности и применять к нему функцию max, будет применяться лямбда-функция ко всему объекту DataFrameGroupBy, который возвращает нам DataFrame с городом в качестве индекса. Если вы посмотрите на результат ниже, то теперь у нас есть город в виде столбца и индекса.

Теперь с этим DataFrame мы можем снова сгруппировать по городам и получить первую запись из каждой группы, и это будет нашим решением. Но если мы это сделаем, мы получим исключение, поскольку thetown является одновременно уровнем индекса и меткой столбца, что неоднозначно.

Что мы можем сделать, так это сбросить индекс перед выполнением другой группы. Мы сможем это сделать к df.reset_index(drop=True). Параметрdrop=True предотвратит добавление индекса в качестве столбца к результирующему фрейму данных. Или лучше то, что мы можем использовать существующую опцию as_index=False метода groupby, что приведет к аналогичному результату.

Посмотрите на решение ниже, и мы сможем найти самого симпатичного кота в городе с именем мяу или похожим на него.

Но это не соответствует нашему ожидаемому решению 😳. Для Дели мы ожидаем кошку с идентификатором 5, а не 3. Нам не хватает одной части задачи, мы должны отдать предпочтение кошке, имя которой больше мяу, чем имя которой похоже на мяу.

Для этого мы добавляем еще одно поле оценки. Предполагая, что имя кошки не может содержать более 100 слов, мы можем дать оценку каждой кошке, используя формулу (cuteness of cat * 100) — length of the name. Так что, даже если привлекательность обеих кошек равна 10. Кошка Мяу получит 10*100-4 = 996, а Камео наберет 10*100-6 = 994. Что интересно, наши оценки никогда не пересекались бы с разной привлекательностью. Например, если привлекательность равна 10, оценка будет в диапазоне от 10*100-100 = 900 до 10*100-4 = 996. А если привлекательность 9, оценка будет в диапазоне от 9*100-100 = 800 до 9*100-4 = 896. Так что мы можем смело использовать эту формулу.

Чтобы добавить новый столбец в наш DataFrame, мы можем просто сделать что-то вроде ниже.

Итак, теперь для нашего окончательного решения мы можем заменить сортировку по привлекательности на total_score, и мы получили правильный результат. 🤗

Спасибо за чтение! Прокомментируйте, если у вас есть какие-либо сомнения или вы чувствуете, что знаете лучший способ «Найди Мяу!»

P.S: Готовы к вызову самый милый кот в городе ? Напишите в Твиттере свое лучшее решение для Pandas с хэштегом # cutest-cat-per-town, #findingmeow 👨‍💻 или оставьте комментарий ниже. Если мы найдем ваше решение лучше, чем наше, мы включим ваше сообщение вместе с вашим именем.