7.34K subscribers
1.74K photos
75 videos
1 file
1.32K links
Привет! Мы — образовательная платформа в сфере аналитики Simulative: simulative.ru

Создаём курсы-симуляторы, где обучаем не на «апельсинках», а на кейсах из реального бизнеса.

Наш уютный чат: @itresume_chat
Поддержка: @simulative_support
Download Telegram
😱 Будьте аккуратны с последовательностью JOIN в SQL-запросах

Проверяя работы студентов в нашем Симуляторе, мы постоянно сталкиваемся с одной и той же ошибкой:

Люди пренебрегают порядком джоинов в запросе, что ведет к неправильному результату и даже потере данных!

Приведем пример для иллюстрации этой ошибки. Пусть нам даны 3 таблицы:

* Таблица с задачами Problem
* Таблица с тегами TagList
* Таблица со страницами сайта Page
* Таблица-связка задач и тегов ProblemTag

А теперь давайте попробуем написать 2 запроса:

1. Выведем все задачи со всеми соответствующими каждой задаче тегами, а также информацию о странице по каждой задаче
2. Выведем все задачи со всеми соответствующими тегами, а также информацию по каждому тегу

Допустим первый запрос мы написали так:

select *
from problem p
left join problemtag p2
on p.id = p2.problem_id
join page p3
on p.page_id = p3.id

А второй запрос так:

select *
from problem p
left join problemtag p2
on p.id = p2.problem_id
join taglist t
on t.id = p2.tag_id

🟢 А в чем, собственно, ошибка?

По идее, учитывая поставленное задание, количество строк в этих двух запросах должно совпадать. Это логично - в обоих запросах мы отталкиваемся от таблиц Problem и ProblemTag, а меняется только последний джоин. Однако, именно он и является критичным.

Если мы посмотрим на количество строк, то заметим, что во втором запросе мы потеряли строки. Вот так выглядит количество строк:

В первом запросе - 524
Во втором запросе - 451
В таблице ProblemTag - 451
Задач, для которых нет ни одного тега - 73

И вот теперь мы видим, что во втором запросе мы потеряли ровно все задачи, для которых нет ни одного тега!

🟢 Как так получилось?

Очень просто - во всем виновата последовательность джоинов:

1. В первом запросе с помощью left join мы сохраняем все задачи, даже если для них нет тегов. А последний джоин эти задачи не отсеивает, потому что соединяет таблицы Page и Problem, для которых есть соответствие в каждой строке.
2. А во втором запросе последний джоин отбрасывает все задачи без тегов! Это происходит потому что в join фигурирует таблица ProblemTag. Т.к. джоин обычный (inner join), остаются только строки из ProblemTag, а значит все задачи, для которых нет тегов просто выкидываются из расчета.

Получается, во втором запросе left join не имеет никакого смысла и его эффект перебивается последним join? Да, именно так. И это очень частая ошибка, которая встречается во многих боевых задачах. А самое страшное, что ее реально сложно заметить.

🟢 Как исправить?

Есть несколько способов исправить такой запрос:

1. Изменить порядок джоинов (перенести left на последнее место и заменить на right)
2. Вместо последнего inner join также указать left join

Например:

select *
from problemtag p
join taglist t
on t.id = p.tag_id
right join problem p2
on p2.id = p.problem_id


А вы допускали такую ошибку? На всякий случай проверьте свои рабочие скрипты, вдруг туда затесался враг 😁

- - - - -
🔗 Залетайте в Симулятор «Аналитик данных» 👉🏻 https://vk.cc/ch76dC и не делайте таких ошибок 🙃
👍9🔥4
🔥 Давайте проведем live coding?

Ребят, у нас возникла идея - а давайте покодим в прямом эфире? Например, решим какое-нибудь тестовое задание по SQL или Python на позицию Аналитика Данных 🙃

🟢 Если вам нравится эта мысль - поставьте, пожалуйста, реакцию на это сообщение. Так мы поймем, что интерес есть и в ближайшее время вернемся с приглашением 🤟🏻

P.S. Если вы хотите другую тему для лайвкодинга - напишите об этом в комментариях. Мы с удовольствием возьмем ее в работу.

P.P.S. Если у вас есть классное тестовое задание, которые было бы круто порешать в прямом эфире - напишите в личку
@andron233
🔥108👍33
🔥 Лайвкодинг: «Ща порешаем» в новом Симуляторе «Аналитик данных» с Глебом Михайловым

Недавно мы предложили провести лайвкодинг и вы с энтузиазмом восприняли эту идею.

Поэтому мы решили сделать даже круче: мы дали Глебу Михайлову (кто ж не знает Глеба) доступ к одной главе нашего нового Симулятора «Аналитик данных».

📌 В воскресенье в 19:00 МСК приходите на стрим - Глеб будет делать распаковку симулятора и решать топовые бизнесовые задачи на SQL.

Кстати, крутой подгон - мы также дадим каждому участнику доступ к главе и к задачам: сможете кодить вместе с Глебом 🤟🏻

Короче, ждем всех в воскресенье в 19:00 - будет классно. Посмотрим, сможет ли Глеб симулировать аналитика данных 😈😂
👍18🔥8🎉3
🔥 Начинаем лайвкодить SQL через 5 минут

Это напоминалка о том, что через 5 минут мы начинаем стрим с Глебом. Будем решать крутые задачки по SQL в рамках нашего нового Симулятора «Аналитик данных».

🔗 Ссылка на стрим: https://youtu.be/2jDFud5hRHM. Подключайтесь, будет круто!

Хотите решать вместе с нами? Вот вам ссылочка на Главу 6 «Группировки и агрегации», которую и будет проходить Глеб 👉🏻 https://lms.simulative.ru/gleb/6/1/leopard

А если хотите залететь в Симулятор по выгодной цене - то просто введите промокод dataleopard15 на сайте, он даст вам 15% скидки 😏
👍53
🔥 Долой длинные строки в Python

Во время код-ревью мы часто сталкиваемся с длинными строками кода, которые даже не влезают в экран. И казалось бы - они содержат настолько «стройную» информацию, что даже не знаешь, где (и зачем) поставить перенос на следующую строку.

Вот несколько случаев, где это встречается особенно часто:

* Длинные строки
* Большое количество аргументов в функции
* `method chaining` в Pandas

Рассмотрим такой «длинный» код на примере Pandas. Согласитесь, выглядит жутко:

df = coderun[coderun["cohort"] >= "2022-01"].groupby(["cohort", "language", "user_id"])["problem_id"].agg("nunique").groupby(["cohort", "language"]).agg(np.mean).reset_index().pivot_table(values="problem_id", columns=["language"], index=["cohort"])

А теперь давайте приведем код в порядок. Есть, как минимум, два метода борьбы с такими ситуациями.

🔵 Перенос строки с помощью обратного слеша

Достаточно поставить в конце строки обратный слеш и Python будет воспринимать весь написанный код как единую строку.


df = coderun[coderun["cohort"] >= "2022-01"] \
.groupby(["cohort", "language", "user_id"])["problem_id"] \
.agg("nunique") \
.groupby(["cohort", "language"]) \
.agg(np.mean) \
.reset_index() \
.pivot_table(values="problem_id", columns=["language"], index=["cohort"]


Сами видите - код стал в разы более читаемым и даже компактным.

🔵 Оборачивание круглыми скобками

Прием заключается в том, что мы просто оборачиваем все выражение в круглые скобки и это тоже рассматривается Python как одна строка кода.


df = (
coderun[coderun['cohort'] >= '2022-01']
.groupby(['cohort', 'language', 'user_id'])['problem_id']
.agg('nunique')
.groupby(['cohort', 'language'])
.agg(np.mean)
.reset_index()
.pivot_table(values='problem_id', columns=['language'], index=['cohort'])
)


На наш взгляд, этот вариант даже лучше - нет лишних символов и код выглядит еще более аккуратным.

- - - - -

Кстати, а вы знали про method chaining в Pandas и про способы переноса строк?
🔥24👍3
🔥 Ищем технического редактора (автора контента) к себе в команду

Друзья, мы расширяем команду и ищем человека, который будет помогать нам с контентом во всем его многообразии. Естественно, все на 100% связано с программированием и аналитикой. Вот примеры задач:

* создавать задачи и тесты для нас и наших корпоративных клиентов
* создавать посты в соцсети
* создавать обучающие материалы, пособия, шпаргалки и т.д.

Если вам это интересно - почитать про вакансию можно по ссылке (там же небольшое тестовое):

🔗 ссылка на вакансию

Работа очень интересная и масштабная - каждую единицу созданного вами контента будут видеть и использовать тысячи людей 🔥 Будем ждать вас в нашу команду 🙂

P.S. Идеального знания языков программирования не требуется.

- - - - -

А если эта вакансия может быть интересна вашим друзьям/родственникам/коллегам - обязательно перешлите им, пожалуйста.
👍51
🔥 Агрегирование в Pandas, которым вы не пользовались раньше (наверняка)

Работая с библиотекой Pandas, нередко приходится применять функции группировки и агрегирования. Все мы привыкли к sum, count и прочим распространенным функциям.

Но сегодня нам хотелось бы рассказать об одной интересной функции, которую можно использовать в агрегации. Речь пойдёт о функции set. Она позволит вывести уникальное множество значений для каждой группы.

Более наглядно рассмотрим работу функции на небольшом примере. Представим, что у вас есть датафрейм с id клиента и с наименованием его покупки:

| id | product |
|----|---------|
| 1 | p1 |
| 2 | p2 |
| 1 | p3 |

Для отображения уникальных покупок каждого клиента воспользуемся такой конструкцией:

df.groupby('id').agg({'product': set})

В результате мы получим таблицу:

| id | product  |
|----|----------|
| 1 | {p1, p3} |
| 2 | {p2} |

А какими способами вы бы решили данную задачу? 😏

- - - - - - - - - -

🔗 Хотите прокачаться в аналитике? Ждем вас в Симуляторе «Аналитик данных» →
🔥26
🔥 Можно ли обойтись без OFFSET в SQL?

Команда LIMIT позволяет вывести ограниченное количество записей из таблицы. Например:

SELECT * FROM table
LIMIT 10

Данный запрос выведет первые 10 строк из таблицы.

Но что делать, если необходимо вывести строки, начиная со второй? Скорее всего, вы воспользуетесь командой OFFSET, и это будет верным решением.

Однако, так же можно решить эту задачу следующей конструкцией:

SELECT * FROM table
LIMIT 1, 10

Команда LIMIT отсекает 1 строку и берет следующие 10, которые идут после неё.

⛔️ Обратите внимание, что такой способ работает не во всех СУБД!

Если в MySQL можно написать такой запрос, то в PostgreSQL он выдаст ошибку и придётся воспользоваться командой OFFSET. А в MSSQL так и вовсе нет оператора LIMIT, в этой СУБД используют команду TOP.

- - - - - - - - - -

🔗 Хотите прокачать свой SQL? Заходите решать задачки на платформу IT Resume →
🔥16👍2
🔥 Метрика N-day Retention - важнейшая метрика продукта

Если вы работали с продуктовой аналитикой, вы наверняка слышали о метрике Retention. Но знаете ли вы, что есть несколько видов данной метрики?

Мы решили подготовить для вас небольшие шпаргалки по каждому виду Retention. Начнём, пожалуй, с классической метрики.

N-day Retention - метрика, которая показывает, какой процент клиентов продолжает пользоваться продуктом в конкретный день после знакомства.

Данная метрика является одной из основных. Мало привлечь внимание клиентов к своему продукту, важно ещё и удержать как можно большее количество пользователей.

Рассмотрим как рассчитать n-day Retention на примере.

1 сентября 100 человек познакомились с нашим продуктом (например, установили приложение). Мы решили посчитать n-day Retention седьмого дня. Считаем количество пользователей, которые воспользовались приложением 8 сентября, т.е. спустя 7 дней со дня установки. Таких клиентов оказалось 37. Находим долю этих клиентов:

(37 / 100) * 100% = 37%

То есть мы удержали 37% новых пользователей. Это и есть n-day Retention на седьмой день.

В итоге, чем выше значение n-day Retention, тем меньше отток клиентов.

P.S. стоит так же обратить внимание на специфику продукта. К примеру приложение по поиску авиабилетов будет иметь значение данной метрики ниже, чем соцсеть.

- - - - - - - - - -

🔗 Хотите научиться считать не только n-day, но и другие виды retention в SQL, Excel и не только? Приходите в симулятор “Аналитик данных”!
🔥9👍1
🔥 Лайфхак: работа с датами в связке Excel - Python

Нередко возникают моменты, когда при создании датафрейма на основе Excel файла, даты записываются в различных форматах. Сегодня нам бы хотелось рассмотреть случай, когда дата имеет числовой формат.

Рассмотрим, например, дату 10.01.2022. Если преобразовать её в число в Excel, мы получим 44571, а в Python - 738165.

Для получения даты в числовом виде в Python мы использовали такую конструкцию:

import datetime
datetime.date(2022, 1, 10).toordinal()
# 738165

Почему так происходит? Дело в том, что Excel начинает отсчёт с 1900 года, а Python с 1 года.

И как же быть в таких ситуациях? На помощь приходит библиотека xlrd.

Переведём число 44571 в дату используя конструкцию ниже:

from xlrd.xldate import xldate_as_datetime
print(xldate_as_datetime(44571, 0))
# 2022 - 01 - 10 00:00:00

Браво! Вы великолепны! Вот так с помощью двух строчек можно преобразовать даты к одному формату!

- - - - - - - - - -

🔗 Приходите к нам на платформу, у нас есть интересные задачи на Python и не только: IT Resume
👍10🔥4🎉1
🔥 Ищем технического редактора (автора контента) к себе в команду

Друзья, мы расширяем команду и ищем человека, который будет помогать нам с контентом во всем его многообразии. Естественно, все на 100% связано с программированием и аналитикой. Вот примеры задач:

* создавать задачи и тесты для нас и наших корпоративных клиентов
* создавать посты в соцсети
* создавать обучающие материалы, пособия, шпаргалки и т.д.

Если вам это интересно - почитать про вакансию можно по ссылке (там же небольшое тестовое):

🔗 ссылка на вакансию

Работа очень интересная и масштабная - каждую единицу созданного вами контента будут видеть и использовать тысячи людей 🔥 Будем ждать вас в нашу команду 🙂

P.S. Идеального знания языков программирования не требуется.

- - - - -

А если эта вакансия может быть интересна вашим друзьям/родственникам/коллегам - обязательно перешлите им, пожалуйста.
🔥61👍1
🔥 Извлекаем абсолютно любые числа из строки с помощью регулярного выражения

Представьте, что вам дана строка, содержащая:

✓целые/дробные положительные/отрицательные числа
✓числа в стандартной записи и в научной записи (2e-10)
✓абсолютно что угодно еще

🧠 А теперь решите задачу:

Нужно извлечь из этой строки только числа, притом во всех форматах.

Как это сделать? А давайте воспользуемся регулярными выражениями! Для примера возьмем строку:

s = '(3.22128 какой-то текст 0.353403 -0.0194664 еще какой-то текст 2e-15 some more text 15. 5 50e -100 )'

А теперь напишем такой код:

import re

[eval(el[0]) for el in re.findall('(-?\d+(e-\d+|.\d+)*)', s)]

🧐 На выходе мы получим список из чисел и ничего лишнего. Но как это получилось?!

💡А очень просто: здесь с помощью регулярного выражения мы находим «кусочки», которые удовлетворяют шаблону. Давайте дадим небольшой комментарий:

-?

Перед числом может стоять знак «минус», а может и не стоять.

\d+

Затем идет некая последовательность цифр (либо целая часть числа, либо основание в научной записи)

(...|...)*

Затем может идти один из вариантов, разделенных |

e-\d+

Научная запись: символ e, после которого идет - и какая-то последовательность цифр

.\d+

Дробная часть: точка, а после нее цифры

(...)

Финально оборачиваем все в скобки, чтобы извлечь полное число, а не его дробную/целую часть

С помощью сервиса regex101 вы можете удобно протестировать все возможные вариации строк с этой регуляркой. Работает железно и достойно ваших сохраненок 😁

- - - - -

🔗 Хотите научиться также просто решать боевые задачи? Приходите в симулятор «Аналитик данных»!
🔥24👍2
🔥 Приходите к нам на онлайн мастер-класс по SQL

Завтра проводим бесплатный онлайн мастер-класс по SQL. Будем вас ждать! 😍

Ваш первый кейс в аналитике данных: исследуем продажи аптек

🎄 Дата: 21 декабря, среда
🎄 Время: 20:10 по Мск
🎄 Площадка: Youtube
🎄Бесплатно

Будем разбираться в SQL, обсуждать разные фишечки, писать ad-hoc запросы и анализировать деятельность реального бизнеса. Короче, будет интересно!

Ссылка на подключение и раздаточный материал придет сюда → ссылка, подписывайтесь 🙂
🔥12👍3
🔥 Уже скоро начнется наш онлайн мастер-класс по SQL

Напоминаем, что сегодня в 20:10 по Мск мы проводим мастер-класс по SQL. Что будем делать:

* Анализировать программу лояльности в аптечной сети
* Считать продуктовые метрики: LTV, ARPPU и другие
* Обсуждать интересные функции и приемы (unpivot, age и многое другое)

🔗 Ссылочка на вебинар, доступ к реальному кластеру и конспект-методичка доступны здесь 👉🏻 ссылка

Приходите, будет интересно! 🙂
👍4🔥21🤩1
Друзья, мы начинаем! 🔥

Ссылка на мастер-класс 👉🏻 https://www.youtube.com/watch?v=VhlgGlNn8B8
👍3🔥21
«Пишем цикл в одну строку» или list comprehension

При проверке домашних работ наших студентов мы часто натыкаемся на конструкцию такого вида:

lst = [1, 2, 3]

result = []
for el in lst:
if el % 2 == 0:
result.append(el)

Однако, Python замечателен тем, что позволяет писать элегантный, и почти такой же простой для чтения код, как обычный английский. Поэтому, можете даже не сомневаться, почти всегда есть возможность, сделать Ваш код короче. В нашем примере можно использовать list comprehesion.

result = [i for i in lst if i % 2 == 0]
>> [2]

🧠 Давайте разберемся как это работает.

Новый список = [выражение for элемент in iterable (if условие)]

✓ В выражении мы можем задать только элемент, вызвать какой-либо метод или обозначить выражение, возвращающее значение.

For элемент in iterable - это та же конструкция, которую мы используем в циклах for.

✓ А условие позволяет нам, одновременно с генерацией списка, добавлять фильтрацию.

Если Вы думаете, что это и так уже достаточное упрощение, Python снова позволяет нам сделать еще больше, и все в одну строку!

Что если нам нужны три условия?

result = [i for i in lst if i % 2 == 0 and i > 1 or i == 3]
>> [2, 3]

Или такая конструкция:

result = [i**2 for i in lst if i % 2 == 0 or i in [5, 9, 4, 7]]
>> [1, 4]

Тут уже непонятно кто кого проверяет на прочность. То ли мы Python, то ли Python нас…

Но давайте попробуем прочесть: для каждого i в lst, возвести i в квадрат и если i**2 четное или есть в переданном в условие списке - добавить в result. Уже стало понятнее!

💡 Прекрасно, скажете Вы, мы можем написать 4 строки кода в одной, а есть ли в этом практический смысл?

Допустим, у нас есть список из 10000 элементов, нам нужно его отфильтровать и сформировать новый. Цикл for отработает за 417 µs, а list comprehension - за 289 µs. Почти в два раза быстрее.

Теперь у вас есть не только эстетическая мотивация разобраться, но и практическая. А когда станет совсем легко, приглашаем ознакомиться с двойным list comprehension, мы рассказывали про него здесь!
🔥12👍81
🔥 «Большой О» уже стал вашим другом?

Обращали ли Вы когда-нибудь внимание на то, за сколько времени отрабатывает Ваш код?

Когда мы учимся, мы думаем «хорошо, что вообще отработал». Однако, в дальнейшем, это может сыграть злую шутку. Когда Вы приступите к большим проектам (а мы в этом не сомневаемся), придется чаще думать над ускорением работы, уменьшением объема памяти и многих других вещах. А BIG O или О-нотация станет Вашим большим помощником.

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

Как же тогда это оценивать?

Ответ: BIG O или О-нотация - Ваш неизменный помощник в вопросе сложности алгоритма.

Главное! BIG O показывает то, насколько сильно увеличивается время работы при увеличении входных данных. Это гораздо лучшая метрика для оценки, чем конкретное время работы!

Давайте сразу к примерам:

O(n): при n=1 делается 1 шаг. При n=10 делается 10 шагов.
O(n²): при n=1 делается 1 шаг. При n=10 делается 100 шагов.

Заметьте, при n=1 эти двое будут работать одинаково!

Еще один замечательный пример: линейный и бинарный поиск.

Не вдаваясь в подробности, сложность линейного поиска - O(N), выглядит неплохо. Это, по сути, означает, что при увеличении входных данных в 2 раза, понадобится в 2 раза больше времени. Если данных будет в 100 раз больше, то и времени нам потребуется x100.

Сложность бинарного поиска - O(log N). Немного посчитав, обнаружим, что при увеличении входных данных, например, в 100 раз, затраченное время увеличится не в 100 раз (как в примере выше), а всего в 2,5 раза.

Существенная экономия, и это при условии, что BIG O оценивает худший вариант - то есть искомый элемент будет самым последним.

Решить одну и ту же проблему зачастую можно многими способами. Задача умелого программиста — выбрать самый подходящий. Знание таинственной O-нотации поможет заранее понимать как алгоритм будет проявлять себя в работе. Звучит как конкурентное преимущество, неправда ли?

Мы ближе познакомимся с BIG O в следующих постах, следите за обновлениями!

🏋️‍♀️ А пока разминка 👉 вы сможете написать алгоритм для чисел Фибоначчи за О(1)?
🔥7👍51🤩1
🔥 Ключевая метрика нашего бизнеса - rolling retention. Шпаргалка.

Встречайте rolling retention. Продолжаем нашу серию шпаргалок. Мы уже рассказывали вам про n-day retention вот 👉🏻 тут.

Давайте освежим ваши знания. Допустим, у нас 2 пользователя, один пользователь вернулся на 14-й день и на 45-й день, а второй пользователь - только на 44-й день. Каким будет n-day retention 14 дня? Верно, 50%. А rolling retention будет 100%. Как? А вот как!

❗️Rolling retention - это процент пользователей, которые вернулись к продукту в день N с момента знакомства или в любой из последующих дней.

🟢 Давайте сразу посмотрим пример.

У нас есть данные по 4 пользователям за 6 дней. Дни, когда пользователи взаимодействовали с продуктом - выделены галочкой, если поле пустое - пользователь был неактивен.

Посчитаем для них «классический» retention и rolling.

           | **День 1** | **День 2** | **День 3** | **День 4** | **День 5** | **День 6** 
-----------|------------|------------|------------|------------|------------|------------
User 1 | ✓ | ✓ | ✓ | | ✓ | ✓
User 2 | ✓ | ✓ | | ✓ | |
User 3 | | | | | |
User 4 | | ✓ | | | | ✓
Retention | 2/4 50% | 3/4 75% | 1/4 25% | 1/4 25% | 1/4 25% | 2/4 50%
Rolling | 3/4 75% | 3/4 75% | 3/4 75% | 3/4 75% | 2/4 50% | 2/4 50%

Заметно, что rolling retention выше, чем “классический”, потому что он учитывает не только пользователей, которые были активны в один конкретный день, но и всех тех пользователей, которые вернулись позже.

Однако, на практике, с rolling retention бывают сложности. Например, у нас были пользователи, которых мы посчитали «отвалившимися», и при расчете rolling retention мы перестали их учитывать, а они вдруг взяли и вернулись! Теперь нам придется пересчитать rolling retention за все предыдущие дни. Но не пугайтесь сразу, обычно эта метрика считается динамически на дашбордах и т. п., так что эту работу за Вас сделает сама BI-система или интерактивный отчет 😊

Например, в последний раз пользователь был активен в 10-й день после первого контакта с продуктом. Затем мы рассчитали rolling retention на 25-й день, уже более не рассматривая этого пользователя. Однако он проявил активность на 30-й день. И чтобы учесть это - потребуется обновить rolling retention за все дни с 11-го по 30-е.

💡Где же это может быть удобно?

В то время как «классический» retention удобен для продуктов, которые используются ежедневно: соцсети, почта, игры. Rolling retention будет идеален для продуктов нерегулярного пользования, например, сайтов продажи авиабилетов. Он явно покажет, что пользователь может не быть активным каждый день, но все еще оставаться с нами. А еще мы в IT Resume активно используем эту метрику 😀

🎁 Хотите освоить аналитику данных с нуля на кейсах из реальной бизнес-практики? Присоединяйтесь к симулятору «Аналитик данных» со скидкой 50% до 31 декабря → ссылка на Симулятор

#продуктовые_метрики
🔥7👍3🤩1
Кто сидит с телефона - прикладываем табличку в виде картинки, чтобы было лучше видно 🙂
🔥92
🔥 3 строки, которые написал бы middle в Pandas

1️⃣

Используете ли вы .query? Зачастую, когда необходимо отфильтровать датафрейм мы видим следующую конструкцию:

df.loc[(df['Adults'] < 3) & (df['Children'] > 1)]

В выбранном здесь синтаксисе нет ничего плохого. Однако многие новые пользователи забывают, что в Pandas можно писать большие запросы, используя .query:

df.query('Adults < 3 and Children > 1')

И чем сложнее будут становится ваши запросы, тем сильнее вы прочувствуете полезность .query.


2️⃣

Часто бывает так, что у нас есть переменная, к которой мы хотим обратиться в запросе. Как бы Вы это сделали? Наш топ встречаемого кода:

- Конкатенация

df.query('Adults < ' + str(min_adults) + 'and Children > ' + str(min_children))

- f-строки

df.query(f'Adults < {min_adults} and Children > {min_children}')

А знали ли вы, что ко внешним переменным можно просто обратиться через @?

df.query('Adults < @min_adults and Children > @min_children')


3️⃣

И напоследок, используя .query нам бывает необходимо сформировать из результирующего датафрейма - новый.

df_families = df.query('Adults < 3 and Children > 1')

Однако, когда мы решим изменить новый датафрейм, мы получим предупреждение SettingWithCopyWarning.

df_families['First_name'] = df_families['Name'].str[-5:]

Дело в том, что Pandas позволяет нам выполнять, так называемую, цепную индексацию. Это повторный выбор строк/столбцов из результата предыдущего выбора строк/столбцов. Однако же, при подобных манипуляциях, предсказать что вернет нам Pandas - копию или представление - практически невозможно. Поэтому, чтобы обезопасить себя и быть уверенным в том, что модификации не появятся там, где их не ждали, лучше воспользоваться методом copy().

df_families = df.query('Adults < 3 and Children > 1').copy()

df_families['First_name'] = df_families['Name'].str[-5:]

Он, по умолчанию, создаст глубокую копию и любые изменения в нашем новом датафрейме не отразятся в оригинальном.

- - - - -

🎁 Присоединяйтесь к симулятору «Аналитик данных» со скидкой 50% до 31 декабря → ссылка на Симулятор

#python #pandas
👍19🔥7🤩1
🔥 Типичная ошибка в SQL: приоритет операторов

Часто в обучении встречаются задачи, где в WHERE нужно передать несколько условий, и, порой, остальной запрос может быть верным, но будет возвращать некорректный результат из-за приоритета операторов.

Живой пример: у нас есть таблица с информацией о разработчиках, которая содержит ФИО, язык разработки и уровень (junior/middle/senior).

Если нам нужно будет выбрать только middle и senior, мы запросто используем запрос:

SELECT ...
WHERE level = 'middle' OR level = 'senior'

(Надеемся вы знаете, что если вместо OR поставить AND- получим совсем не то, что нужно)

Усложняемся: найдем всех middle и senior, пишущих на Python:

SELECT ...
WHERE level = 'middle' OR level = 'senior' AND language = 'python'

Все верно? Вот что мы получим:

| name    | language | level  |
|---------|----------|--------|
| Дмитрий | python | senior |
| Валерий | php | middle |
| Наталья | python | middle |
| Валерия | python | middle |

В результирующей таблице появился php-разработчик, а мы его, как будто, и не просили.

Дело в том, что операторы OR и AND имеют разный приоритет, и у AND он - выше. Запрос сначала выбирает senior, использующих python, а далее срабатывает OR, который добавляет всех middle.

Чтобы получить верный результат можно написать:

SELECT ...
WHERE level = 'middle' AND language = 'python' OR level = 'senior' AND language = 'python'

А лучше еще проще:

SELECT ...
WHERE (level = 'middle' OR level = 'senior') AND language = 'python'

Когда в одном запросе Вам приходится использовать и OR, и AND - обращайте внимание на порядок выполнения, иначе можно запросто получить неверные данные. Особенно, если не знать, как выглядит исходная таблица и необходимый результат. А чтобы полностью обезопасить себя от ошибок с OR и AND - используйте скобки.

Легко заметить ошибку, когда мы явно видим, что не все строки удовлетворяют нашему условию, но когда строк миллион - найти такую ошибку будет уже невозможно.

Чувствуете уверенность в этой теме? Попробуйте решить задачу!

#sql
🔥20👍82