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

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

Наш уютный чат: @itresume_chat
Поддержка: @simulative_support
Download Telegram
🔥19
🔥 Нестандартная ситуация со словарями

Мы знаем, что вы - любите Python, а еще больше любите необычные фишки. Но знали ли вы, что при работе со словарями могут возникать довольно не интуитивные ситуации?

Посмотрите, чему будет равен my_dict?

my_dict = {
1.0: 'One (float)',
1: 'One (int)',
True: 'One (bool)',
'1': 'One (string)'
}

# {1.0: 'One (bool)', '1': 'One (string)'}

Несмотря на добавление 4 отдельных ключей в словарь, можете ли вы объяснить, почему он оставляет только два из них?

Мы знаем, что ключи должны быть уникальными и неизменяемыми. В данном случае нет никаких сомнений в том, что 1.0, 1 и True имеют разные типы данных.

type(1.0), type(1), type(True)

# (float, int, bool)

Если посмотреть на их id, убедимся что и они различны:

id(1.0), id(1), id(True)

# (139644507527152, 139645051222320, 9758592)

Но дело не только в этом! Ключи должны быть еще хешируемы. Для поиска ключа, Python использует именно его хэш-значение, а не id. Значит посмотрим на их хэш-значения:

hash(1.0), hash(1), hash(True)

# (1, 1, 1)

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

📎 Но обратите еще внимание на итоговые ключ и значение: ключ - 1.0, в то время как значение соответствует ключу True.

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

Дело в том, что сначала 1.0 добавляется в качестве ключа, а значение устанавливается 'One (float)'. Затем, добавляя ключ 1, python распознает его как эквивалентное хэш-значение. И значение, соответствующее 1.0, перезаписывается на 'One (int)', в то время как ключ (1.0) сохраняется как есть.

Наконец, при добавлении True снова получаем эквивалентность хэша с существующим ключом 1.0. И снова, значение, которое изначально было 'One (float)' и обновлено до 'One (int)' на предыдущем шаге, перезаписывается на 'One (bool)'.

А почему сохранен строковый ключ '1'?

Тут все просто: он имеет уникальное хеш-значение, отличное от других ключей.

💥 Надеемся, что этот пост дал вам чуть более полное понимание работы словарей. Приходите к нам на Симулятор "Аналитик данных", где мы с нуля обучаем SQL и Python и делимся полезными фишками!

#python
🔥20👍6
💥 А вы знакомы с оператором MERGE в PostgreSQL?

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

🟣 Так что же такое MERGE?

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

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

Обычно такое обновление можно выполнить в стороннем приложении. Проблема только в перетаскивании данных туда-сюда, которые вероятно придется сделать несколько раз (из базы в приложение, и обратно), а это много дополнительных издержек (в данном случае времени).

🖋 Но с недавнего времени в этом нет необходимости, благодаря MERGE все можно легко сделать прямо в базе.

Для работы с MERGE нужны две таблицы. Таблица с обновлениями и основное хранилище данных - целевая таблица. Содержимое таблицы с обновлениями сравнивается с целевой, и в целевой таблице происходят изменения.

🔵 Как это работает?

Начнем с двух таблиц и одной строки данных.

create table a (id int, x int, status char(10));

create table b (id int, x int, status char(10));

insert into a (id, x, status) values (1, 1, 'From a');

select * from a;
select * from b;

id | x | status
---+---+------------
1 | 1 | From a
(1 row)

id | x | status
---+---+--------
(0 rows)

Теперь мы можем попробовать MERGE в запросе. Таблица a содержит одну строку, а в таблице b - строк вообще нет. И в запросе записи, не включенные в целевую таблицу, мы вставляем, а те, которые есть, обновляем:

MERGE into b using a on a.id = b.id
when matched then
update set x = b.x + 1
when not matched then
insert (id, x, status) values (a.id, a.x, a.status);

Запрос сообщает - сопоставь две таблицы по id. Если есть строки, которые совпадают, то столбец x в таблице b увеличь на единицу. Но если совпадений нет (совпадения не будет, так как таблица b пуста), то содержимое строки из таблицы a копируется в таблицу b. Если мы теперь посмотрим на обе таблицы, мы увидим, что они идентичны.

select * from a; 
select * from b;

id | x | status
----+---+------------
1 | 1 | From a
(1 row)

id | x | status
----+---+------------
1 | 1 | From a
(1 row)

🟢 А что если запустить MERGE снова?

Указанная в запросе логика будет выполнена, и значение столбца x увеличится с 1 до 2.

select * from a; 
select * from b;

id | x | status
---+---+------------
1 | 1 | From a
(1 row)

id | x | status
---+---+------------
1 | 2 | From a
(1 row)


И, каждый раз, когда мы перезапускаем запрос с MERGE - x будет увеличиваться.

🟡 Можем и удалить!

Мы можем не только обновлять (UPDATE) значения, но и удалять их. Например, давайте изменим наш запрос так, чтобы не увеличивать значение, а удалять строку в целевой таблице, если найдутся соответствующие строки.

merge into b using a on a.id = b.id
when matched then delete
when not matched then
insert (id, x, status) values (a.id, a.x, a.status);

select * from b;

id | x | status
----+---+--------
(0 rows)

Примечание: операция MERGE доступна только в PostgreSQL 9.5 и более поздних версиях.

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

#sql #interview_problems
🔥18👍6
🔥 Продуктовая метрика LIFETIME

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

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

Это как раз показатель востребованности продукта, заинтересованности юзеров и, более того, «гарантия» их финансовой активности. И этот показатель - Lifetime.

Lifetime - это среднее время, в течение которого пользователь остается активным.

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

Как считать?

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

Есть несколько способов расчета lifetime.

🟢 Наиболее точный способ

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

Например, у нас есть когорта из 100 пользователей, и мы знаем, сколько дней они провели в проекте прежде, чем покинули его:

| Число клиентов | Кол-во дней |
| 30 | 1 |
| 20 | 7 |
| 10 | 14 |
| 10 | 18 |
| 10 | 22 |
| 5 | 31 |
| 5 | 40 |
| 5 | 45 |
| 5 | 54 |

В этом случае их lifetime равен 15,6 дням.

Но, чувствуете подвох? Расчет точного lifetime может занять достаточно много времени и это почти невозможно в реальной жизни, поскольку придется ждать, пока все пользователи окончательно прекратят использовать продукт.

Поэтому обычно мы, грубо говоря, оцениваем lifetime, а не считаем его. И при оценке мы опираемся в большей степени на retention.

🟡 Второй способ

Одним из способов оценить lifetime будет определение «точки невозврата», когда неактивные определенное количество дней (7, 14, 30) юзеры, считаются «отвалившимися».

🟣 Третий способ

Другой способ - вычисление интеграла от retention (поскольку lifetime - это площадь под кривой retention) или простое суммирование всех показателей retention. Для такого подсчета нам нужно знать retention за несколько дней, чем больше, тем лучше, так как это будет влиять на точность оценки.

Что нам дает lifetime?

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

Вот поэтому он очень полезен - он дает общую картину продукта всего одним числом.

При работе с lifetime обращайте внимание на сегментацию. Можно делить пользователей по-разному: по стране, полу, устройству, а можно делить по проведенному времени с продуктом. То есть отдельно посмотреть на поведение юзеров с lifetime = неделя, две, месяц - вы сможете увидеть зависимости и, скорее всего, понять причины оттока.

Разница между Lifetime и Lifetime Value

Мы не раз видели подобные вопросы от наших студентов. Тут важно понимать, что LTV больше финансовая метрика (буквально наш доход от юзера за его lifetime). И хотя lifetime, в отличие от LTV, мы измеряем не в рублях, он все равно очень влияет на доход. Чем выше lifetime, тем дольше пользователь будет совершать платежи. Для сервисов с подпиской, это, пожалуй, особенно важные метрики.

💥 Более подробно обсуждаем продуктовые метрики: какие бывают, как считать, где применять, как анализировать на нашем Симуляторе «Аналитик данных»!

#analytics #продуктовые_метрики
🔥10👍42
🔥6
🔥 Возможно, вы не знали этого о циклах for в Python

Недавно поступил вопрос от наших студентов, которые недавно освоили for-loop в Python и принялись экспериментировать.

💡 Загадка

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

for i in range(5):
print(i)
i = 10

#0
#1
#2
#3


Как видно, переменная i не меняется, хотя мы попытались ее переназначить внутри цикла.

🟡 На самом деле, когда мы используем for-loop в Python, никто, как правило, не имеет намерений изменить переменную цикла внутри него. Но можно догадаться, откуда растут ноги. 🙂 Возможно, так могли бы поступить те, кто уже знаком с другими языками программирования, например, С++ или Java.

Но в питоне for-loops не работают таким образом. Изменение переменной цикла не влияет на итерацию.

При каждой итерации цикла for Python извлекает следующий элемент из указанного итерируемого объекта (iterable) - например, range(5). Затем значение этого элемента присваивается переменной цикла - например, i.

То есть после выполнения range(5) или любого другого range(n), объект, созданный range, становится абсолютно независящим от изменений на протяжении итераций. Будто мы написали цикл: for i in [0, 1, 2, 3, 4].

🖋 А теперь комментарий от наших преподавателей

Если вам действительно необходимо переназначить переменную цикла, используйте while, о котором частенько забывают, как только знакомятся с for-loop:

i=0
while i < 5:
print(i)
i = 10

#0

Или:

i=0
while i < 5:
print(i)
i += 2

#0
#2
#4

Это довольно простая вещь, но о ней стоит помнить при разработке!

👉 Записывайтесь на наш бесплатный курс по Python, где вы с нуля освоите новый язык программирования!

#python
👍14🔥9
🔥 Тонкости функции head в Pandas

Сегодня мы поделимся любопытной деталью из мира аналитики данных и нашей практики. Если вы работаете с Pandas, то наверняка знакомы с методом head(). Он позволяет вывести первые n рядов вашего датафрейма.

🟡 Но у head() есть нюанс. Если данные содержат повторяющиеся значения, head() просто вернет первые строки и не станет учитывать их. Показываем пример:

import pandas as pd

df = pd.DataFrame(
[['Игорь', 95],
['Яна', 100],
['Петр', 97],
['Иван', 95]],
columns = ['Имя', 'Оценка'])

df.sort_values('Оценка', ascending=False).head(3)

| | Имя | Оценка |
|---|-------|--------|
| 1 | Яна | 100 |
| 2 | Петр | 97 |
| 0 | Игорь | 95 |

В данном случае мы отсортировали датафрейм по столбцу 'Оценка' и просим вывести три первых позиции. Но если обратить внимание на значения оценок, то заметите, что у двух людей они равны. И если эти данные для вас важны, то использование head() может быть ошибкой.

🖋 Такие моменты часто имеют значение, например, при анализе транзакций, чтобы получить список n продуктов с самыми высокими продажами. Или мы, анализируя активность на itresume.ru при отборе страниц с наибольшим количеством посещений, не можем ограничиться head() - нам важны все значения (даже повторяющиеся).

🟢 И чтобы избежать этого, мы используем метод nlargest() вместо head(). Он позволяет извлекать верхние k строк отсортированного датафрейма, учитывая повторяющиеся значения. Давайте рассмотрим пример:

df.nlargest(n=3,
columns='Оценка',
keep='all')

| | Имя | Оценка |
|---|-------|--------|
| 1 | Яна | 100 |
| 2 | Петр | 97 |
| 0 | Игорь | 95 |
| 3 | Иван | 95 |

Здесь мы указываем желаемое поведение для повторяющихся значений, используя параметр keep. В данном случае просим сохранить все строки с равными наивысшими оценками.

‼️ В нашем бесплатном курсе по Python рассказываем, как работать с модулями и библиотеками Python: как устанавливать, импортировать и какие могут быть подводные камни ☺️

#python #pandas
🔥22👍13
🔥 CTE-запрос вместо case/when конструкций

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

📎 Недавно мы наткнулись на очень любопытную конструкцию! Допустим, имеется таблица температур в различных локациях weather_stations:

| station | temperature |
|---------|-------------|
| Moscow | 18.40 |
| Paris | 20.90 |
| London | 14.50 |
| Rome | 23.10 |

P.S.: Данные, очевидно, фейковые 🙂

🟣 Какая самая классическая задача для такой таблицы? Да, распределить значения на: жарко, тепло, холодно. Как чаще всего это реализуется? С помощью нескольких case/when конструкций: (карточка 1)

🟢 Понятная классика! А мы нашли кое-что интереснее: CTE-запрос, с использованием numrange (карточка 2)

Не сказать, что эта запись короче, но посмотрите на сам подход!

👨🏻‍🎓 Те, кто не знаком с типами диапазонов, могут смутиться, увидев конструкцию '( 0,10)' и тип данных numrange.

Numrange - один из нескольких диапазонных типов, и он предназначен для диапазона числовых значений (бывают еще tsrange - для timestamp, daterange - для дат и другие).

Возвращаясь к математике: круглые скобки означают, что граничные значения не входят в диапазон, а квадратные, что входят. Таким образом, '(0,10]' означает "от 0, но не включая 0, и до 10 включительно".

Отсутствующее значение '[36,)' означает любое значение после, если это второе значение, или любое значение до, если первое - '(,0]'.

И последнее: необычный оператор <@ означает включен ли некоторый элемент в некоторый диапазон.

🤔 Может показаться, что это ненужное усложнение обыденной задачи, но спешим не согласиться! Данная задача - конечно проста, для облегчения понимания, но в условно больших таблицах бывает необходимо категоризировать несколько столбцов. Тогда для каждого из них придется писать case/when конструкцию. А формирование такого универсального CTE избавит от повторяющихся фрагментов и повысит читабельность.

Вдобавок, для изменения или дополнения параметров категоризации, во втором варианте (в отличие от case/when) нам не придется затрагивать основной запрос - просто вносим правки в CTE и готово!

#sql
🔥16👍3🎉1
🔥25👍3
🔥 Создание поля объектов в Python с помощью setattr()

В работе с Python порой возникают ситуации, когда нужно динамически создавать поля объектов. Например, вы можете столкнуться с задачей занесения данных из словаря в атрибуты класса (мы столкнулись с такой задачей 🙂).

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

🟢 Один из способов решения этой задачи - использовать функцию setattr(). Эта функция позволяет динамически назначать поля объекта во время выполнения программы. Она принимает три аргумента: объект, имя атрибута и значение атрибута.

Например, предположим, что у нас есть словарь my_dict:

my_dict = {
    'name': 'Максим',
    'age': 25,
    'city': 'Москва'
}

Мы можем создать объект Person и использовать функцию setattr() для присвоения значений атрибутам:

class Person:
    pass

p = Person()
for k, v in my_dict.items():
     setattr(p, k, v)

В результате мы получим объект Person с атрибутами name, age и city.

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

💡 Кроме того, функция setattr() может пригодиться в других ситуациях, когда нужно динамически создавать поля объекта. Например, при работе с API или базами данных, когда набор полей может меняться в зависимости от запроса пользователя.

‼️ Чтобы освоить или улучшить свои навыки программирования на Python, присоединяйтесь к нашему бесплатному курсу!

#python
🔥12👍7
🔥 Как «распаковать» массив в PostgreSQL?

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

На самом же деле все просто. В PostgreSQL есть множество функций, связанных с массивами. Начнем с unnest() - самой простой для понимания, на наш взгляд.

🟢 Функция unnest() позволяет "распаковать" массивы в строки. Это очень удобно, если нужно отобразить массивы в виде простой таблицы.

В более старых версиях PostgreSQL для этого приходилось использовать медленные и сложные методы, но с unnest() все стало гораздо проще.

Как использовать функцию unnest() в PostgreSQL?

Просто передайте ей массив, и она "распакует" его значения в строки таблицы.

Синтаксис: unnest(array)

🟡 Например, если есть массив с числами от 1 до 5, то можно применить функцию unnest() и получить каждое число в отдельной строке таблицы.

SELECT unnest (ARRAY[1,2,3,4,5]);

|   | unnest |
|---|--------|
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |

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

SELECT unnest (ARRAY['яблоко', 'лимон', 'банан']);

|   | unnest  |
|---|---------|
| 1 | яблоко |
| 2 | лимон |
| 3 | банан |

Видим, что она работает одинаково как для строковых значений, так и для чисел.

А что насчет многомерных массивов?

SELECT unnest (array[array[1, 2], array[2, 3], array[4,5]]);

|   | unnest |
|---|--------|
| 1 | 1 |
| 2 | 2 |
| 3 | 2 |
| 4 | 3 |
| 5 | 4 |
| 6 | 5 |

А если с несколькими массивами разных типов данных? Запросто.

Мы просто будем использовать синтаксис unnest (array1, array2, array3…):

SELECT * FROM
unnest
(
array [1, 2, 3],
array ['HP', 'AMD', 'APPLE']
)
AS data(ID, Company);

| | id | company |
|---|----|---------|
| 1 | 1 | HP |
| 2 | 2 | AMD |
| 3 | 3 | APPLE |

А если они разных размеров?

SELECT * FROM
unnest
(
array [1, 2, 3],
array ['HP', 'AMD', 'APPLE', 'DELL']
)
AS data(ID, Company);

| | id | company |
|---|--------|---------|
| 1 | 1 | HP |
| 2 | 2 | AMD |
| 3 | 3 | APPLE |
| 4 | [NULL] | DELL |

Если массивы имеют разное число элементов, то функция автоматически дополнит их NULL - значениями до нужного размера.

🖋 А теперь попробуйте решить такую задачку:

> У вас есть таблица "books", где для каждой книги указаны ее ID и список авторов (хранится как массив). Используя функцию unnest(), найдите все книги, написанные авторами, чьи имена начинаются на букву "A".

Пишите ваши запросы в комментариях!

#sql
👍12🔥8
🔥 Вакансия: Data Scientist (нейронные сети)

Сегодня мы с крутой новостью - ищем Data Scientist по направлению AI к себе в команду.

🔹 Направление: детекция объектов/текстов на изображениях (object detection, OCR)

🔹 Формат: удаленка, проект, частичная занятость/фултайм, с возможностью дальнейшего роста в международном стартапе

🔹 Опыт: от 1 года, наличие проектов object detection/OCR в портфолио

Присылайте свои резюме на почту a.alexanyan@itresume.ru и напишите в письме - почему именно вы подходите для этой вакансии 🙂

Будем рады видеть вас в команде! 🤩
🔥8👍2
🔥 Степени свободы в статистике

Как-то мы делали пост о различиях расчета стандартного отклонения в NumPy и Pandas. И пообещали вам напомнить, а что же такое эти степени свободы, в которых вся соль. Сегодня об этом и поговорим.

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

Формула: Степени свободы = Количество независимых значений - Количество статистик

Пример. У нас есть 50 независимых значений, и мы хотим вычислить одну статистику - "среднее". Согласно формуле, степеней свободы будет 50 - 1 = 49.

🟢 Давайте представим, что вы проводите эксперимент, в котором измеряете рост 10 человек. Вы знаете среднее значение роста этих людей. Однако если бы вы измеряли рост еще большего количества людей, то среднее значение могло бы отличаться от результата, который вы получили изначально.

Почему? Во-первых, потому что мы берем лишь подмножество данных. А во-вторых, потому, что у нас есть ограничения в количестве данных, которые мы можем использовать. Эти ограничения и определяют степень свободы в нашем эксперименте.

Возвращаемся к стандартному отклонению. Как его считать?

1. Вычислите среднее значение набора данных.
2. Вычтите среднее значение из каждого значения в наборе данных.
3. Возведите в квадрат разности, полученные на шаге 2.
4. Сложите квадраты разностей, найденных на шаге 3.
5. Разделите сумму, полученную на шаге 4, на N (если берем генеральную совокупность) , либо на (N - 1) (если берем выборку). На этом этапе мы получили дисперсию.
6. Извлеките квадратный корень из результата шага 5, чтобы получить стандартное отклонение.

🟡 Концептуально мы можем понять это следующим образом: если бы мы имели доступ ко всей генеральной совокупности, мы могли бы точно вычислить истинное значение стандартного отклонения. Но если мы используем выборку, то у нас есть только ограниченный объем информации, который может привести к искажениям (и порой значительным).

Таким образом, мы должны скорректировать выборочную дисперсию, чтобы учесть этот факт. И именно поправка N-1 в знаменателе, позволяет учитывать этот фактор.

🟠 Вернемся к эксперименту с ростом людей.

Допустим, 10 человек - это генеральная совокупность, значения - [150, 193, 173, 184, 168, 201, 178, 175, 180, 182].

Используя NumPy, посчитаем стандартное отклонение генеральной совокупности: 13.14. Возьмем условную «выборку» - пять последних элементов, и посчитаем теперь для них.

import numpy as np

a = [201, 178, 175, 180, 182]
np.std(a)

# 9.195

Вспомним, что NumPy считает стандартное отклонение для генеральной совокупности (в знаменателе N - без степеней свободы), а мы уже работаем с выборкой, и нам нужно добавить одну степень свободы (N-1). Посмотрим, приблизимся ли мы к изначальному результату.

import numpy as np

a = [201, 178, 175, 180, 182]
np.std(a, ddof=1)

# 10.28

Действительно, стало поточнее. Конечно, 10 элементов с трудом можно назвать генеральной совокупностью, а половину - выборкой. Но убедиться, что это работает, можно!

Итог: используя степени свободы, вы получите несмещенную оценку, и это обеспечит вам более точные результаты. Поэтому не забывайте, что в NumPy по умолчанию ddof=0, а в Pandas ddof=1.

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

#analytics #pandas #numpy
🔥9👍52
🔥 Бесплатный live-курс по SQL для начинающих 🔥

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

На связи Андрон, CEO Simulative & IT Resume.

Хочу пригласить вас на свой бесплатный live-курс по SQL для начинающих: "Сегментация базы пользователей", который пройдёт с 16 по 17 мая в 19:00 по мск. 💥

Этот live-курс подойдет Вам, если:

🔹 У вас совсем нет опыта в SQL;
🔹 Вы немного владеете базовым SQL, но нет системности;
🔹 Вы никогда не применяли SQL для решения бизнес-задач.

На live-курсе помимо лекций будут 2 блока домашних заданий, доступ к боевому кластеру и реальный бизнес-кейс, который вам предстоит решить самостоятельно.

КУРС АБСОЛЮТНО БЕСПЛАТНЫЙ! 😉

🔗 Чтобы не пропустить трансляцию и получить конспект, переходите по ссылке 👉 https://mnlp.cc/mini?domain=simulative&id=7.

До встречи! 🙂
🔥8👍3🤩2
💥 Напоминание о бесплатном live-курсе по SQL 💥

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

Возможно, вы пропустили наш прошлый пост, поэтому дублируем информацию еще раз 🙃

Приглашаем вас на бесплатный live-курс по SQL для начинающих: "Сегментация базы пользователей", который пройдёт с 16 по 17 мая в 19:00 по мск. 🔥

Что вас ждет на live-курсе:

🔸 2 живых обучающих лекции с разбором практических заданий;
🔸 2 блока домашних задания (15 заданий);
🔸 Самостоятельное решение бизнес-кейса с обратной связью от преподавателя;
🔸 Доступ к боевому кластеру;
🔸 Работа с профессиональными инструментами и программами.

🔗 Чтобы не пропустить трансляцию и получить конспект, переходите по ссылке 👉 https://mnlp.cc/mini?domain=simulative&id=7.

До встречи на live-курсе! 😉
🔥9👍2
⁉️ А есть ли разница между Concat / Сoncat_ws / ||

Как часто вас учат, что можно заменить функцию concat оператором ||? А что, если мы скажем, что это не совсем так? Мы вместе с нашими студентами курса разбирались в этом во время решения домашних задач.

✏️ В PostgreSQL оператор || - это бинарный оператор, который используется для конкатенации двух строковых значений. Он просто соединяет две строки вместе, не добавляя никаких разделителей или других символов между ними.

SELECT 'IT' || 'Resume';
-- ITResume

В то время как функции concat() и concat_ws() также используются для конкатенации, но предоставляют некоторые дополнительные возможности. Например, функция concat() позволяет объединять любое количество строковых аргументов, а concat_ws() еще и принимает первым аргументом разделитель.

SELECT concat('IT', ' ', 'Resume');
-- IT Resume

SELECT concat_ws('-', '2023', '05', '15');
-- 2023-05-15

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

А что с NULL значениями?

Вот и ловушка! При использовании оператора || в PostgreSQL, если один из аргументов NULL, результат будет также NULL. Например:

SELECT 'SQL' || NULL;
-- NULL

А вот функции, вполне справятся с NULL значениями:

SELECT concat(NULL, NULL);
-- ''

SELECT concat_ws(' ', 'IT', NULL, 'Resume');
-- IT Resume

Почему так?

Оператор || работает по стандарту SQL, когда любое выражение, в котором участвует NULL должно равняться NULL. Потому что NULL это неизвестность. Как 42 * NULL даст NULL.

А функции concat и concat_ws если какой-то из элементов NULL - проигнорируют его и соединят остальное, но если все NULL - вернут пустую строку.

❗️ Так что будьте осторожны и присоединяйтесь к Симулятору «Аналитик данных», чтобы оценить свои навыки на рабочих кейсах!

#sql
🔥15👍5
📢 [Ласт-колл] на бесплатный live-курс по SQL для начинающих

Это Андрон, основатель IT Resume & Simulative. Просто хочу напомнить, что сегодня в 19:00 по мск пройдет первый день бесплатного live-курса по SQL для начинающих: "Сегментация базы пользователей"

🔗 Чтобы не пропустить трансляцию и получить конспект, переходите по ссылке 👉 https://mnlp.cc/mini?domain=simulative&id=7.

До встречи на трансляции! 😉
🔥42👍1
🤨 Действительно ли параметр inplace в Pandas ускоряет операции?

Многие пользователи Pandas считают, что использование операций с параметром inplace=True ускорит работу с датафреймами. Согласны ли вы с этим? Всегда ли это работает?

🟢 Давайте это проверим

Inplace - это параметр методов Pandas, который позволяет изменять DataFrame без создания нового объекта. Звучит так, будто это должно работать быстрее, но есть некоторые нюансы:

- Inplace, вопреки тому, что следует из названия, часто не препятствует созданию копий. Это первый пункт против скорости подобного способа.
- SettingWithCopy - часто получаемое предупреждение - оно не влияет на выполнение кода. Однако же получается Pandas выполняет дополнительные проверки, чтобы убедиться, что датафрейм изменен корректно. Соответственно, второй пункт против скорости inplace.
- И последнее - inplace операции могут быть менее гибкими, так как не позволяют объединить несколько методов в одной строке.

Но это лишь предположения, давайте убедимся в них!

🔵 Мы провели небольшой анализ

Смотрите в карточке под постом как некоторые методы работают с inplace.

❗️Какие-то методы действительно работают быстрее, некоторые гораздо быстрее, но все-таки большинство - медленнее.

Поэтому, перед тем, как применять inplace, обязательно оцените время и потенциальную пользу в вашем конкретном случае и не потеряйте важные данные!

🧠 Если хотите все проверить самостоятельно - делимся ссылкой на коллаб.

#python #pandas
🔥5
🔥8👍3