and other cool things
Катаев Денис
AI Center - Chatbot CTO
4 команды, 30 человек, ищем еще
Продукты:
Активности:
Нравится? Читаемо?
jQuery style lol
Не мутирует данные!
Вообще мутация данных не очень
How NOT to deal with SettingWithCopyWarning in Pandas:
Я думаю у него цель в 1 строку всё сделать
если в df.info() есть object, это в целом красный флаг
ну кроме что строк
Есть типы unsigned которые занимают в 2 раза меньше
Есть типы уменьшенной размерности uint8, float16 и т.д
Фильтруем df по простым условиям
Порой удобно фильтровать в цепочке вызовов
Внутри есть eval
kek = "asd"
df.query("lol = @kek")
df.query("lol = 'lol'")Синтаксис с @kek ломает читаемость, линтеры и автоматические рефакторинг
через .loc[...]
Минус еще один повод иметь ссылку на df{1,2,..._tmp}
index? Что такое индекс?
MultiIndex в индексе или в колонках
Это не для новичков, но корректное использование индексов существенно ускоряет выборки
Если часто берете данные по каким-то полям,
почему бы не засунуть это в индекс?
.loc[df.f1 == '..' & df.f2 == '@@']
Очень крутая штука
связанная с иерархическим индексом
Превращает колонку в df
Задаёт имя колонке в df для той серии
.groupby([...])['f1'].mean().to_frame('f1_mean')
Эффективно соединяет данные по индексу
df.merge более универсальный метод, может работать так же, но более многословен в некоторых ситуациях
Соединяет несколько df
есть аргумент axis позволяет соединять так и сяк
ну и .pipe() если честно
Две большие разницы
df.apply(lambda df: ...)
df[...].apply(lambda val: ...)Пруф что используется векторизированный код
df.assign(
true_intent_id=lambda df: df['intent_id'].where(df['asnwer'] != 'yes', UNK)
)Как то так:
Метод полностью векторизирован
Что это вообще?!
почему питон медленный и почему быстрый
import pandas as pd
import numpy as np
import perfplot
def some_apply(x):
return np.log(x)
out = perfplot.bench(
setup=lambda n: pd.DataFrame(dict(kek=np.random.rand(n))),
kernels=[
lambda df: df['kek'].apply(some_apply),
lambda df: df['kek'].apply(lambda x: np.log(x)),
lambda df: df['kek'].apply(np.log),
],
labels=[
"series_apply_func",
"series_apply_lambda",
"series_apply_lambda_ufunc"
],
n_range=[2 ** k for k in range(20)],
xlabel="len(a)",
)
out.save("perf.png")
Векторизованные методы
https://github.com/pandas-dev/pandas/issues/35864
https://www.gresearch.co.uk/blog/article/faster-string-processing-in-pandas/
В посте разбирает скорость операций над 100 миллион строк
spaCy’s core data structures are implemented as Cython cdef
pandas.Series(['foo', 'bar', 'foobar'], dtype='string[pyarrow]')pydantic для pandas
И mypy даёт по жопе
pytest-snapshot
Сложно зафиксировать эталон, потому что он будет меняться вместе с ETL
Цель улучшить UX когда изменения сознательные!
pytest --snapshot-update
def test_knn_result(tmp_path, snapshot):
snapshot.snapshot_dir = ROOT_DIR / 'snapshots'
dataset = ROOT_DIR / 'data' / 'dataset_junior_test.csv'
df = pd.read_csv(dataset)
builder = KnnReportBuilder(df=df, ...)
assert builder.fit_knn() is None
result = builder.predict()
labels_consistency = (
builder.
calculate_consistency(result, column='label')
.to_frame('score')
)
snapshot.assert_match(
to_snapshot(labels_consistency),
'labels_consistency.jsonl'
)Путь до эталона, чтоб он мог туда записать
def to_snapshot(df: pd.DataFrame) -> str:
return (
df.reset_index()
.to_json(lines=True,
orient='records',
force_ascii=False)
)Генерация случайных данных, тест проходит
Пустой df, т.к в генерации не учли колонку type
но только на 1.1.4
В 1.5 добавили проверку что нельзя вставить пустой df
А prod_data.apply(...) как раз нулевой длины
Я удолил тест
в helicopter и zero copy между dwh и python
подписывайте петицию (её нет)