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

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

Наш уютный чат: @itresume_chat
Поддержка: @simulative_support
Download Telegram
🔥 А ваш churn rate растет или падает?!

Внимание всем причастным к бизнесу! Следите ли вы за churn rate?

Churn rate - это показатель оттока клиентов за некоторый период времени. Обычно он выражается в процентах от общего числа юзеров на начало периода. Если компания имела 100 клиентов и в течение месяца пятеро ушли (отменили подписку, отказались от продуктов и тд), churn rate выходит 5%.

Давайте посчитаем churn rate в SQL:

WITH customer_start AS (
SELECT COUNT(*) as
start_customers
FROM customers
WHERE signup_date <
'2021-01-01'
),
cancelled_customers AS (
SELECT COUNT(*) as
cancelled
FROM customers
WHERE cancel_date BETWEEN
'2021-01-01' AND
'2021-01-31'
)
SELECT (cc.cancelled / cs.start_customers) * 100 as
churn_rate
FROM customer_start cs, cancelled_customers cc

Все очень легко, но есть несколько вещей, которые следует знать при работе с churn rate.

1️⃣ Мы уже много раз упоминали в наших шпаргалках по retention и скажем еще раз. Значения различных метрик будут отличаться по отраслям/специфике и churn rate - не исключение. Не надо сравнивать churn rate Spotify и Госуслуг.

2️⃣ На уровень оттока может влиять множество факторов (политика ценообразования, обслуживание, конкуренция, для оффлайн бизнесов даже переезд клиента может быть фактором). Это важно понимать, чтобы суметь вовремя изменить ситуацию. Вернуть уходящих/ушедших пользователей легче, чем привлечь новых!

3️⃣ К сожалению, churn rate не расскажет нам о том, какие юзеры ушли и почему, а также не учтет тех, кто может уйти в скором времени. Churn rate - это сухие факты. А для всего остального есть, например, показатели удовлетворенности клиентов, индекс потребительской лояльности и RFM анализ.

Следить за churn rate необходимо, чтобы в один прекрасный день не обнаружить «спонтанный» отток клиентов. Так что, держите руку на пульсе и повышайте лояльность пользователей. Ведь если вы предоставляете исключительный сервис, и клиент лоялен, то он останется с вами надолго, а churn rate не будет расти!

_ _ _ _ _ _ _

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

#продуктовые_метрики
🔥7👍3
🔥 Попрощаемся с длинным форматированием строк в Python

Аналитики, разработчики и все, кто работает с Python, вы замечали что пишут про f-строки практически в каждом источнике? Если нет, то вот цитата «f-строки - новейший и наиболее лаконичный способ форматирования». Согласны? Хотелось бы немного уточнить формулировки.

Новейший? F-строки были впервые представлены в PEP 498, в 2015 году! Уже почти 10 лет назад. 🤔 Даже версия python - 3.6, в которой они были впервые представлены, более не поддерживается командой разработчиков. Так что с новейшим мы бы поспорили, но если вы еще не оценили весь функционал f-строк, скорее читайте пост, ведь знать это нужно было еще вчера.

🔴 Отдадим дань истории

До появления f-строк в Python существовало два популярных способа форматирования строк: %-formatting и format(). %-форматирование считается наименее читаемым по сравнению с другими методами, и его использование постепенно сходит на нет (остаются только самые стойкие - например, некоторые коннекторы к БД все еще используют только %-formatting).

Format() был введен как более читаемая альтернатива, но, порой, код может стать таким длинным (особенно при форматировании сложных строк), что читабельность этого метода окажется под вопросом.

🔵 Наконец перейдем к самому удобному способу!

Суть F-строк в том, что для форматирования достаточно просто встроить выражение в строку. Самый простой пример:

name = "ITResume"
age = 2
f"Hello, my name is {name} and I am {age} years old."

>> Hello, my name is ITResume and I am 2 years old.

В фигурных скобках можно использовать любое допустимое выражение. Сложение, вычитание, деление, даже лямбда-функцию (правда зачем, но можно, главное обернуть её в скобки):

f"{(lambda x: x*2)(3)}"

>> 6

Еще, с помощью f-строк, мы можем задать параметры форматирования. Например, количество знаков после запятой:

pi = 3.14159265
f"The value of pi is approximately {pi:.2f}."

>> The value of pi is approximately 3.14.

Или даже так:

import datetime

date = datetime.date(1991,10,12)
f"{date} was on a {date:%A}"

>> 1991-10-12 was on a Saturday

Разве этого недостаточно для звания самого удобного инструмента форматирования? Если нет, то для самых искушенных - использование if внутри f-строки:

my_str = 'hello'
f"Result: {my_str.upper() if len(my_str) > 1
else my_str.capitalize()}"

>> Result: HELLO

На наш взгляд, это довольно убедительные аргументы в пользу того, что f-строки - мощный и универсальный инструмент в Python. Лаконичный синтаксис, широкие возможности, удобство, все это - причина их использовать. И если вдруг, вы были среди тех, кто избегал f-строк - самое время прощаться с полотнами не очень разборчивого кода и переходить к кратким и гибким методам!

_ _ _ _ _ _ _

🧠 Попробуйте решить задачу с помощью f-строк

#python
👍19🔥6
🔥 NULL в SQL больше 10 или меньше?

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

Вы хотите отсортировать отчет по стране спортсмена, но также, вы хотите выделить спортсменов, у которых не указан возраст, чтобы связаться с ними, и уточнить эту информацию.

Уже знаете как это сделать?

Это именно та ситуация, где вступают в игру NULLS FIRST и NULLS LAST.

🔸 В SQL значение NULL - это специальный маркер, используемый для указания того, что данные отсутствуют. По умолчанию строки с нулевыми значениями сортируются так, будто они больше любого ненулевого значения.

То есть по умолчанию для порядка АSC (по возрастанию) используется NULLS LAST - нулевые значения будут стоять последними, а для DESC - NULLS FIRST - будут первыми. Однако могут быть случаи, как раз как наш, когда необходимо отсортировать нулевые значения по-другому: при сортировке по возрастанию показать нули первыми.

Тут нам и пригодится NULLS FIRST! Запишем запрос:

SELECT name, age, country
FROM athletes
ORDER BY country, age NULLS FIRST;

Этот запрос отсортирует спортсменов сначала по стране, а затем по возрасту, причем спортсмены с неуказанным возрастом будут отображаться первыми. И для примера, попробуем использовать NULLS LAST для сортировки спортсменов с отсутствующим возрастом - последними, а не первыми:

SELECT name, age, country
FROM athletes
ORDER BY country, age NULLS LAST;

🔹 Таким образом, использование параметров сортировки NULLS FIRST и NULLS LAST может дать вам больше контроля над тем, как сортируются значения NULL, что облегчит поиск тенденций и отсутствующих данных. А также сделает поведение вашего кода более очевидным как для вас, так и для других.

❗️ Попробуйте включать их в свои запросы и убедитесь в том, как они упростят работу со значениями NULL!

#sql
🔥26👍12
🔥 3 способа вывести первую строку в GROUP BY

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

Имеется таблица товаров products, в ней - id товара, его название, категория и цена. (см. таблицу во вложении)

Задача: собрать сливки - самые дорогие продукты в каждой категории.

🟣 Что приходит первое в голову? Взять MAX(price)? Группируем по категории и берем максимальную цену - все гениальное просто!

SELECT category,
MAX(price) as price
FROM products
GROUP BY category;

| category | price |
|-------------|-------|
| Media | 20 |
| Stationery | 5 |
| Electronics | 1500 |
| Literature | 20 |

А если нужно еще показать ID товара? Так просто уже не получится. Но можем воспользоваться оконной функцией ROW_NUMBER. Каждую категорию отсортируем по убыванию цены, присвоим каждой строке в категории номер (1, 2, 3 и т.д.) и возьмем только строку с 1 номером. Элегантно? И главное работает!

SELECT category, id, price
FROM (
SELECT id, category, price,
ROW_NUMBER() OVER
(PARTITION BY category
ORDER BY price DESC)
as rn
FROM products
) x
WHERE rn = 1;

| category | id | price |
|-------------|----|-------|
| Electronics | 7 | 1500 |
| Literature | 3 | 20 |
| Media | 9 | 20 |
| Stationery | 6 | 5 |

Но есть еще несколько неочевидных способов!

🟢 Альтернативным вариантом будет array_agg - эта функция вернет все ненулевые значения в столбце в виде массива. А указав [1] мы возьмем только первое значение. Неочевидно и оригинально.

SELECT (array_agg(id ORDER BY 
price DESC))[1] AS id,
category,
max(price) AS price
FROM products
GROUP BY category;

🔴 И вишенка на торте - DISTINCT ON. Его используют для возврата только первой строки в каждой группе, определенной с помощью ORDER BY. Мы указываем в ORDER BY сортировку по категории и по убыванию цены, таким образом первой строкой для каждой категории (DISTINCT ON (category)) будет строка с самой высокой ценой в категории. Так мы получили самый короткий запрос!

SELECT DISTINCT ON (category)
id, category, price
FROM products
ORDER BY category, price DESC;

Вот три оригинальных подхода к решению проблемы, которая частенько может возникнуть на работе. А козырнуть на собеседовании знанием оконных функций и небольших фишечек SQL - приятный бонус! 😉

_ _ _ _ _ _ _

🔵 Приходите в Симулятор «Аналитик данных», чтобы профессионально овладеть SQL, Python, Продуктовыми метриками и другими инструментами аналитика!

#sql
🔥22👍5🤩3
Таблица products
🔥6
🔥 Сокращаем память в 8 раз в Python

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

🔹 Вот, что мы имеем: скрипт генерирует случайную машину (её марку и цвет) и записывает в список. На выходе мы получаем список из одного миллиона машин.

car_names = ['Toyota', 'Honda', 'Renault', 'Audi', 'Nissan', 'Suzuki']

colors = ['Black', 'Blue', 'Red', 'Yellow', 'White']

def car_list(cnt_cars):
all_cars = []
for i in range(cnt_cars):
car = {
'id': i,
'name': random.choice(car_names),
'color': random.choice(colors)
}
all_cars.append(car)
return all_cars

cars = car_list(1000000)

Может показаться, что задача довольно искусственная, кому может понадобиться список миллиона случайных машин. Но дело не в машинах. Нам часто приходится работать с большими объемами данных. Поэтому и тренироваться мы будем пусть и на “dummy”, но больших данных.

Вернемся к нашему скрипту. Он выполняется за 1,5 секунды в среднем, но это не самое страшное в нем. До генерации списка он использует 8 MB памяти, а после - 334 MB. Конечно, чего мы ожидали от списка в миллион элементов. Но если мы просто сгенерируем его и запишем в переменную - это никуда не годится. Столько используемой памяти может быть непростительной ошибкой, тем более, что мы знаем как это исправить!

car_names = ['Toyota', 'Honda', 'Renault', 'Audi', 'Nissan', 'Suzuki']

colors = ['Black', 'Blue', 'Red', 'Yellow', 'White']

def car_list_gen(cnt_cars):
for i in range(cnt_cars):
car = {
'id':i,
'name':random.choice(car_names),
'color':random.choice(colors)
}
yield car

for car in car_list_gen(1000000):
pass

И, внимание! Немного изменив тело функции, мы сократили время работы до 1,37 секунды, но это не самое интересное. Мы сократили используемую память: с 334 MB до 40 MB. А что мы сделали? Вместо return в функции, использовали yield.

🔸 Справка: yield в Python используется для создания генераторов. Генератор - тип коллекции, которая генерирует элементы на ходу и может быть итерирована только один раз.

Конечно, эта уловка сработает, если вам не нужен доступ ко всем элементам списка сразу.

А вообще, генераторы - хороший способ повысить производительность. Главное - понимать когда и где их использовать.

⁉️ Кстати, сделать отдельный пост о том, как работает yield и в каких задачах его лучше использовать?

#python
👍44🔥7👎1🎉1
🔥 Красивое сравнение нескольких столбцов

У нас имеется таблица students, она содержит информацию о студентах (очевидно). В столбце level указан академический уровень учащегося (Senior, Junior, Freshman и т.д.), subject - предмет, который студент изучает (Math, Physics и другие), а grade - текущая оценка студента по этому предмету (A, B, C и т.д.).

Нам нужно достать всех студентов, которые соответствуют следующим критериям:

- Уровень - 'Senior'
- Изучают 'Math'
- Имеют оценку 'А'

Но подождите, это еще не все! Мы хотим написать как можно более короткий и читаемый запрос. Попробуем? 💡

SELECT level, subject, grade
FROM students
WHERE level = 'Senior'
AND subject = 'Math'
AND grade = 'A';

Вероятно, это первое, что приходит в голову. Но у нас есть для вас один секрет. Мы можем использовать настоящую магию сравнения нескольких столбцов:

SELECT level, subject, grade
FROM students
WHERE (level, subject, grade) = ('Senior', 'Math', 'A');

Мы нечасто видим этот метод в запросах, но согласитесь, выглядит лучше.

Есть пример посложнее! Что если нам понадобятся seniorы, которые лучшие либо в математике, либо в физике?

SELECT level, subject, grade
FROM students
WHERE level = 'Senior'
AND (
(subject = 'Math' AND
grade = 'A')
OR
(subject = 'Physics' AND
grade = 'A'));

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

SELECT level, subject, grade
FROM students
WHERE level = 'Senior'
AND (subject, grade)
IN (('Math', 'A'),
('Physics', 'A'));

Вот как мы аккуратно и компактно решили все задачи! На этом нужно акцентировать внимание, ведь подход «лишь бы работало» - непрофессиональный! Независимо от того, являетесь ли вы опытным аналитиком или только начинаете знакомиться с базами данных, уделяйте время изучению Best Practices, это облегчит вашу работу в будущем!

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

#sql
👍23🔥132👎1
🔥 Необычная «связка» функций для поиска похожих слов в SQL

Один из основных функционалов SQL, которому учат на любых курсах - поиск по шаблону, например, операторы LIKE или SIMILAR TO.

🟢 В PostgreSQL есть необычная функция, которая также относится к поиску в тексте, но может найти не просто заданное слово, а похожие слова или фразы, или даже учесть различные варианты написания. О ней мы сегодня и поговорим!

Если бы мы захотели решить такую задачку самостоятельно, то нам пришлось бы изрядно потрудиться. К счастью, у нас есть функция SIMILARITY и расширение trigram. Это расширение использует триграммы - группы из трех букв. Например, набор триграмм в строке «cat» - « c», « ca», «cat» и «at».

Давайте сразу посмотрим эту связку в деле. Табличка documents содержит совершенно разные строки (см. табличку 1).

Включим расширение trigram в PostgreSQL:

CREATE EXTENSION pg_trgm;

И попробуем с помощью функции SIMILARITY найти слово ellefant. Взгляните на таблицу еще раз и убедитесь, что такого слова нет. Но есть множество других очень и очень похожих слов, и trigram может идентифицировать их как совпадающие.

SELECT title, 
similarity('ellefant', title) AS similarity_score
FROM documents

В столбце similarity_score (см. табличку 2) мы видим числа, описывающие насколько близки два аргумента. Диапазон - от нуля (это значит, что две строки полностью различны) до единицы (две строки идентичны). Что же произошло и как это понимать?

🔵 Наше искомое слово было поделено на триграммы - « e», « el», «ell», «lle», «lef», «efa» и тд, строки в столбце title также поделили на триграммы. И теперь, функция SIMILARITY искала самые похожие триграммы слова ellefant среди триграмм строки title, учитывая порядок. А когда нашла, разделила количество совпадающих триграмм на общее количество триграмм в строке title.

Очень любопытная функция, согласитесь? Расширение trigram, в умелых руках, может повысить точность результатов поиска и упростить поиск нужной информации. Обязательно попробуйте использовать эту в вашем следующем проекте!

😏 А вы знали про такие возможности SQL?!

#sql
👍12🔥9😱6
🔥6👍1
🔥 Знакомимся с «большим О» еще ближе

В одном из прошлых постов мы познакомились с важным понятием при работе с кодом - O-нотация. Надеемся вы еще не забыли что это за зверь? На всякий случай:

BIG O - это способ измерить эффективность алгоритмов и то, как они работают с увеличением объема обрабатываемых ими данных.

💡 Разработчик Python Нед Батчелдер описывает BIG O как анализ того, «как код замедляется по мере роста данных».

Существует множество «классов» сложности, самые популярные из них представлены на картинке под постом. Кажется, ничего лучше нее еще не придумали - все очень наглядно.

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

Допустим, у вас есть книжная полка с n книгами.

🟢 Например, проверить пуста ли книжная полка - операция постоянного времени O(1). Потому что не имеет значения, сколько книг стоит на полке, вам достаточно найти одну книгу, и на этом проверка закончится. То есть в такой задаче количество книг (n) может варьироваться, но время выполнения останется неизменным. Это константная сложность операции - O(1).

🔵 Следующая сложность - логарифмическая O(log n)

- Справка: Логарифмы это обратная от возведения в степень операция: 2^3, или 2 × 2 × 2, равно 8, таким образом логарифм log2(8) равен 3.

Поиск определенной книги на полке в алфавитном порядке - алгоритм логарифмической сложности. Можно воспользоваться бинарным поиском: проверяем, находится ли нужная книга в середине полки. Если да - задача уже выполнена. Если нет, вы можете определить где вам искать дальше - до или после этой средней книги. Таким образом, вы вдвое сокращаете количество книг, среди которых ведется поиск. И этот процесс будет повторяться до тех пор, пока вы не найдёте ту самую.

Если на полке 16 книг, то понадобится не более четырех шагов, чтобы найти подходящую. А если бы на книжной полке было 4,2 миллиарда книг в алфавитном порядке, потребовалось бы всего 32 шага, чтобы найти конкретную книгу.

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

🔴 O(n) - линейная сложность

Прочесть все книги на полке - это линейная по времени операция. Если книги примерно одинаковой длины, и вы удваиваете количество книг на полке, чтение всех книг займет примерно вдвое больше времени. То есть, время выполнения увеличивается пропорционально количеству книг n.

Существуют и другие типы сложности, уже более затратные, мы рассмотрим их в следующих постах, а также поймем как посчитать сложность своего алгоритма. И тогда мы наверняка сможем написать эффективный код, который будет выполняться за адекватное время даже при большом объеме входных данных!

🤩 А если вам уже не терпится узнать все о сложности алгоритмов, забирайте шпаргалку Сложность алгоритмов за 5 минут

#сложность_алгоритмов
👍10🔥4🎉1
🔥7👍3
🔥Какое оно - эстетическое удовольствие аналитика?

Мы очень любим применять в своей работе фишки, конструкции, трюки, если хотите, которые не только удобные, но еще и красивые!

🔹Как часто вы оказывались в ситуации, где вы запустили цикл и ждете, и ждете, и ждете, а он все еще выполняется? Такое может быть если код не очень оптимизирован или вы просто обрабатываете много данных. Иного предсказать сколько времени займет выполнение кода - сложно. И эта неопределенность постоянно щекотит наши нервы.

🪄Что, если мы покажем вам волшебную палочку, которая спасет вас от неизвестности и ожидания! Это волшебство называется TQDM!

С помощью этого модуля вы сможете отследить ход выполнения вашего цикла, да еще и сделать это красиво. Все, что вам понадобится сделать, это импортировать TQDM, и обернуть в него итерируемый объект. Вуаля!

from tqdm import tqdm
from time import sleep
# оборачиваем итератор range(100) классом tqdm()
for i in tqdm(range(100)):
sleep(0.1)

У вас появится автоматически обновляемая строка прогресса:

>> 13%|█▎        | 13/100 [00:01<00:08,  9.82it/s]

А если вы работаете в ноутбуке, можете импортировать tqdm.notebook и тогда эта строка прогресса будет отображаться в html, что делает её еще более интересной (см. гифку под постом).

from tqdm.notebook import tqdm 
from time import sleep

for i in tqdm(range(100)):
sleep(0.1)

Теперь, вам не придется, например, добавлять print в цикл, чтобы понимать на какой стадии вы находитесь. С TQDM вы можете расслабиться и просто наблюдать!

🤩 Очень советуем опробовать этот модуль, потому что это - настоящее эстетическое удовольствие аналитика!

#python
👍12🔥4
🔥 Бесплатный мастер-класс по SQL

Приветствую!

На связи Андрон, основатель IT Resume & Simulative. Хочу пригласить вас на свой мастер-класс по SQL: «Расчет продуктовых метрик и активности пользователей» 🔥

Мастер-класс пройдет 22 февраля, в 20:10 по Мск. Нам предстоит проанализировать активность пользователей платформы IT Resume на основании посещений платформы и решения задач юзерами.

С помощью SQL-запросов мы посчитаем:

- MAU/WAU/DAU
-
sticky factor
- когортный анализ lifetime
методом нахождения интеграла от n-day retention

🔗 Чтобы не пропустить трансляцию и получить конспект, переходите по ссылке 👉🏻 https://t.iss.one/simulative_master_class_bot?start=c1669653664751-ds

Кстати, все участники мастер-класса получат в подарок конспект с разбором метрик, шаблонами SQL-запросов и полезными советами 🎁

До встречи на мастер-классе! 🙂
👍18🔥8
🔥 Задача с собеседования по SQL

Сегодня любимая рубрика - разбор задачи с собеседования!

Есть две таблицы: items_available и colors. Наша задача - извлечь доступные цвета в текстовом формате.

Звучит просто, не так ли? Но как всегда, дьявол кроется в деталях.

items_available

| item_id | colors_available |
|---------|------------------|
| 1 | 1, 2 |
| 2 | 3, 4 |
| 3 | 5, 4 |
| 4 | 3, 4 |
| 5 | 6, 2 |

colors

| color_id | color_name |
|----------|------------|
| 1 | Black |
| 2 | White |
| 3 | Silver |
| 4 | Gold |
| 5 | Pink |
| 6 | Green |

Результат

| item_id | colors       |
|---------|--------------|
| 1 | Black, White |
| 2 | Silver, Gold |
| 3 | Pink, Gold |
| 4 | Silver, Gold |
| 5 | Green, White |

1️⃣ Начнем с первого предложенного варианта решения (карточка 1).

В этом решении столбец colors_available делят на два разных столбца. Это достигается с помощью функций LEFT и POSITION. В POSITION передается запятая и она возвращает нам индекс вхождения этой запятой в строку, а при помощи LEFT мы обрезаем строку до позиции запятой минус единица. Примерно все то же самое происходит для второго числа, только теперь используется SUBSTRING. Дальше все это объединяется c табличкой colors, и с помощью CONCAT - выводят цвета через запятую.

🛑 Этот запрос решает задачу, но не кажется ли вам, что можно сделать запрос короче? Да и в целом, получается какое-то нагромождение.

2️⃣ Итак, версия второго кандидата (карточка 2).

Здесь, мы не используем ни POSITION, ни LEFT, ни SUBSTRING, их всех заменяет SPLIT_PART. В SPLIT_PART можно передать строку, которую мы хотим разделить, потом разделитель (в нашем случае запятая), а затем указать какую часть из получившихся сплитов взять. И мы сразу джойним таблички по этому условию.

Существенно короче и приятнее стал выглядеть запрос, согласитесь?

3️⃣ Но подождите, это еще не все! Третье решение - самое элегантное из всех. Есть только одно НО. Этот запрос сработает, только при условии, что столбец colors_available - не текстовый, а является массивом чисел. (карточка 3)

🟢 В этом случае, нам даже не пришлось придумывать какими пользоваться функциями, нас спас простой ANY. С его помощью мы сопоставляем любой элемент в массиве colors_available с соответствующим id цвета в таблице colors.

У вас есть идеи как еще решить эту задачу? 😏

#sql #interview_problems
🔥13👍6
👍12🔥5
🔥 [Ласт-колл] На бесплатный мастер-класс по SQL

Это Андрон, основатель IT Resume & Simulative. Просто хочу напомнить, что сегодня в 20:10 по Мск я провожу мастер-класс по SQL: «Расчет продуктовых метрик и активности пользователей» 🔥

Будем считать MAU/WAU/DAU, sticky factor и делать когортный анализ lifetime. В конце всех ждут подробные конспекты с шаблонами кода и полезными советами 🎁

🔗 Чтобы не пропустить трансляцию и получить конспект, переходите по ссылке 👉🏻 https://t.iss.one/simulative_master_class_bot?start=c1669653664751-ds

До встречи на мастер-классе 🙂
🔥10👍4👎1
🔥 Генератор yield в Python

Вашей реакции на пост о yield можно только позавидовать. За нами теперь должок, удовлетворить ваш интерес и рассказать об этом загадочном генераторе. Мы посмотрим как это работает и где применимо.

Из примера в прошлом посте видно, что yield можно использовать в функции вместо return. И тогда получается генератор, который вычисляет не всё сразу, а генерирует элемент на ходу.

Итак, как же он работает? 🧐

Допустим, мы хотим получить квадраты чисел от 1 до 10. Мы могли бы создать список и с помощью append добавлять в него элементы, но мы заменим эту привычную конструкцию на yield:

def squares(x=0):
while x < 10:
x = x + 1
yield x*x

for i in squares():
print(i)

Получим:

1
4
9
16
25
36
49
64
81
100

🟢 Что произошло?

Мы задали функцию-генератор squares(), а затем с помощью цикла for вывели элементы, вычисленные функцией.

У генераторов еще есть метод next(). Например, мы бы вызывали next(squares()), чтобы получить следующее значение. Но нам бы пришлось написать это 10 раз, так что лучше воспользуемся циклом.

Итак, при каждой итерации, Python запускал код до тех пор, пока не сталкивался с оператором yield. Затем он выдавал вычисленное значение, а функция, как бы “замораживалась” в этом состоянии, готовясь возобновить выполнение с этого же места.

Когда функция вызывается в следующий раз, выполнение продолжается с этого “замороженного” момента. И так продолжается до тех пор, пока генератор не будет исчерпан. Если после того, как генератор выдал все значения, вызвать его снова - получим ошибку StopIteration. Мы можем переопределить генератор, и тогда все начнётся заново.

🔵 Где пригодится yield?

→ При генерации больших последовательностей - с помощью yield мы сохраним внушительный объем памяти.
→ При чтении больших файлов. Yield позволит пройтись по одной строке за раз, а не считывать весь файла целиком в память.
→ При создании пайплайнов обработки. Вы можете постепенно проходить все этапы для каждого элемента, а не обрабатывать все элементы сразу. Например:

def read_csv(filename):
# читаем строки из файла и обязательно указываем yield
yield line

def filter_columns(rows, indices):
# что-то фильтруем
yield [row[i] for i in indices]

def convert_to_float(rows):
# производим какие-то преобразования
yield [float(cell) for cell in row]

def compute_average(rows):
# производим вычисления
yield total / count

# Создаем пайплайн
pipeline = compute_average(
convert_to_float(filter_columns(
read_csv("data.csv"), [1, 2, 3])))

average = next(pipeline)
print(f"Average: {average:.2f}")

🟡 Таким образом, yield - мощный инструмент, который позволяет создавать генераторы, и получать значения на ходу. Порой, это делает его незаменимым при работе с объемными данными и файлами. Потренируйтесь использовать yield и убедитесь, как он может упростить ваш код и сохранить память!

#python
🔥174👍3