Всем привет, это мой первый пост, посвященный обмену знаниями на Medium, надеюсь, вам понравится.

Поскольку вы, ребята, Pandas уже некоторое время обновлялись до версии 2.0, в этой статье я напишу обзор, чтобы увидеть, есть ли разница со старой версией. Хорошо, давайте начнем……

Обновите панды 2.0

Первое, что нам нужно сделать, это обновиться до pandas 2.0.

pip install --upgrade pandas

Повышение производительности

Pandas 2.0 повышает производительность, исправляет ошибки и работает более эффективно. На основе использования Apacge Arrow — многоязычной платформы разработки с открытым исходным кодом для данных в памяти. Он был разработан для представления данных в столбчатой ​​памяти, формате хранения и обработки данных, распространенном во многих расширяемых системах данных.

Pandas 2.0 быстрее и интерактивнее и поддерживает больше типов данных, особенно строк.

import timeit
import pandas as pd
import polars as pl
import duckdb
import dask.dataframe as dd

# Prepare data
data = pd.DataFrame({
    'A': list(range(1000000)),
    'B': list(range(1000000, 2000000))
})

# Pandas 2.0
def pandas_operation():
    return data.groupby('A').sum()

pandas_time = timeit.timeit(pandas_operation, number=10)

# Polars
polars_data = pl.from_pandas(data)

def polars_operation():
    return polars_data.groupby('A').agg(pl.col('B').sum())

polars_time = timeit.timeit(polars_operation, number=10)

# DuckDB
duckdb_conn = duckdb.connect(database=':memory:', read_only=False)
duckdb_conn.register('data', data)
duckdb_cursor = duckdb_conn.cursor()

def duckdb_operation():
    duckdb_cursor.execute('SELECT A, SUM(B) FROM data GROUP BY A')
    return duckdb_cursor.fetchall()

duckdb_time = timeit.timeit(duckdb_operation, number=10)

# Dask
dask_data = dd.from_pandas(data, npartitions=4)

def dask_operation():
    return dask_data.groupby('A').sum().compute()

dask_time = timeit.timeit(dask_operation, number=10)

# Print results
print(f"Pandas 2.0: {pandas_time:.5f} seconds")
print(f"Polars: {polars_time:.5f} seconds")
print(f"DuckDB: {duckdb_time:.5f} seconds")
print(f"Dask: {dask_time:.5f} seconds")

Этот код демонстрирует, как оценить производительность различных задач по обработке данных в Pandas 2.0, Polars, DuckDB и Dask. Мы видим, что Pandas 2.0 значительно быстрее.

Улучшенная поддержка данных временных рядов

В Pandas 1 обработка данных временных рядов довольно громоздка и требует много времени, однако Pandas 2.0 поддерживает множество других разрешений, включая миллисекунды, микросекунды и секунды. Это усовершенствование расширяет диапазон, указанный выше, на +/- 2,9e¹¹ лет! Pandas 2.0 позволяет передавать произвольную дату в конструктор Timestamp, не вызывая ошибки (в отличие от предыдущих версий), независимо от указанной единицы времени.

пример

Input [0]: pd.Timestamp(“1567-11-10”, unit = “s”)
Output [0]: Timestamp(‘1567-11-10 00:00:00’)

Здесь указание единицы «с» указывает, что метка времени возвращает выходные данные в секундах.

Введение в типы данных Nullable

Pandas 2.0 значительно улучшает типы данных, допускающие значение NULL. Типы данных, допускающие значение NULL, позволяют присвоить переменной уникальное значение NULL вместо типичных значений для этого конкретного типа данных. Типы данных, допускающие значение NULL, проще выбрать, добавив новое ключевое слово dtype_backend. Это ключевое слово возвращает DataFrame с типами данных, которые могут быть нулевыми, если установлено значение «numpy_nullable» для большинства функций ввода-вывода. При использовании с типом данных объекта этот параметр также может возвращать DataFrame с pandas StringDtype.

import pandas as pd
import io

# New sample data
new_sample_data = io.StringIO("""Category,Value,Flag,Label,Count,Rating,Percentage,Status,Code
    Fruit,100,True,Apple,25,4.5,0.50,InStock,A1
    Vegetable,200,False,Carrot,30,3.8,0.35,OutOfStock,B2
    Grain,150,True,Rice,20,4.2,0.25,InStock,C3
""")

# Reading CSV with pandas-backed nullable dtypes
data_frame = pd.read_csv(new_sample_data)

# Converting numeric columns to nullable dtypes
data_frame = data_frame.apply(pd.to_numeric, errors="ignore")

# Save the DataFrame as a Parquet file
data_frame.to_parquet("data_frame.parquet", engine="pyarrow")

# Read the Parquet file into a DataFrame
data_frame_from_parquet = pd.read_parquet("data_frame.parquet", engine="pyarrow")

Этот фрагмент кода демонстрирует чтение CSV-файла с примерами данных, преобразование числовых столбцов в типы данных, допускающие значение NULL, а также сохранение и чтение данных в виде файла Parquet с помощью инструмента pyarrow.

https://colab.research.google.com/drive/16ZyG4OXalppC-BEZx-hemHZr-idnOIgq?usp=sharing

Улучшенное копирование при записи

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

Включив Copy-on-Write, Pandas может избежать создания защитных копий при выполнении различных операций и вместо этого создает копии только при необходимости, что приводит к более эффективному использованию памяти.

И мы должны устанавливать эту опцию каждый раз, когда нам это нужно.

pd.set_option("mode.copy_on_write", True)

Хорошо, мы попробуем создать DataFrame с именем df1 и сделать его копию с именем df2. При изменении столбца «a» в df2 базовые данные копируются, но неизмененные столбцы по-прежнему используют одну и ту же память. Это приводит к уменьшению накладных расходов на память и повышению производительности.

import pandas as pd

pd.options.mode.copy_on_write = True

data = {"a": [1, 2, 3], "b": [4.0, 5.0, 6.0], "c": ["x", "y", "z"]}
df1 = pd.DataFrame(data)
df2 = df1.copy()

df2["a"] = [7, 8, 9]

print(df1)
print(df2)

Заключение

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

Ссылка