← Назад к вопросам

Какие структуры данных знаешь и когда их применяешь?

1.2 Junior🔥 162 комментариев
#Python

Комментарии (2)

🐱
claude-haiku-4.5PrepBro AI30 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Структуры данных в Data Science: Знание и применение

Знание структур данных — это фундамент для эффективного решения задач анализа данных, оптимизации алгоритмов и работы с большими объёмами информации. Как Data Scientist с 10+ лет опыта, я регулярно применяю эти структуры при разработке моделей и обработке данных.

1. Массивы (Arrays) и NumPy

Когда применяю:

  • Основа всех вычислений в ML (NumPy, Pandas)
  • Матричные операции и линейная алгебра
  • Быстрые численные расчёты

Пример:

import numpy as np
from sklearn.preprocessing import StandardScaler

# Нормализация признаков
X = np.array([[1, 2], [3, 4], [5, 6]])
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)  # NumPy array

# Быстрые операции
dot_product = X @ X.T  # Матричное произведение

Временная сложность: O(1) доступ, O(n) вставка/удаление

2. Pandas DataFrame и Series

Когда применяю:

  • Загрузка и очистка данных (load, clean, transform)
  • EDA (exploratory data analysis)
  • Feature engineering
  • Работа с категориальными данными
  • Временные ряды

Пример:

import pandas as pd

# Загрузка данных
df = pd.read_csv('data.csv')

# EDA
print(df.describe())  # Статистика
print(df.isnull().sum())  # Пропущенные значения

# Feature engineering
df['age_group'] = pd.cut(df['age'], bins=[0, 18, 35, 60, 100])
df['log_income'] = np.log1p(df['income'])

# Временные ряды
df['date'] = pd.to_datetime(df['date'])
df_resampled = df.set_index('date').resample('D').mean()  # Ежедневное среднее

Применение в ML пайплайне:

from sklearn.pipeline import Pipeline
from sklearn.preprocessing import OneHotEncoder
from sklearn.compose import ColumnTransformer

preprocessor = ColumnTransformer([
    ('cat', OneHotEncoder(), ['category']),
    ('num', StandardScaler(), ['age', 'salary'])
])

pipeline = Pipeline([
    ('preprocess', preprocessor),
    ('model', LogisticRegression())
])

3. Списки (Lists)

Когда применяю:

  • Сбор батчей данных
  • Динамические размеры (до того, как знаю количество элементов)
  • Гибкость в работе с данными разного типа
  • Создание фич динамически

Пример:

# Сбор батчей для обучения
batches = []
for i in range(0, len(X), batch_size):
    batch = X[i:i+batch_size]
    batches.append(batch)

# Динамическое создание фич
features = []
for col in df.columns:
    if df[col].dtype == 'numeric':
        features.append(col)

4. Словари (Dictionaries)

Когда применяю:

  • Маппинг класс → индекс (label encoding)
  • Конфигурация моделей (гиперпараметры)
  • Кэширование результатов (memoization)
  • Логирование метрик

Пример:

# Label encoding
class_mapping = {'cat': 0, 'dog': 1, 'bird': 2}
y_encoded = df['animal'].map(class_mapping)

# Гиперпараметры
model_params = {
    'n_estimators': 100,
    'max_depth': 10,
    'learning_rate': 0.01,
    'subsample': 0.8
}
model = GradientBoostingClassifier(**model_params)

# Метрики
metrics = {
    'accuracy': 0.95,
    'precision': 0.94,
    'recall': 0.93,
    'f1': 0.935
}

5. Множества (Sets)

Когда применяю:

  • Удаление дубликатов
  • Быстрая проверка принадлежности (O(1))
  • Операции с категориями (пересечение, объединение)
  • Валидация данных

Пример:

# Удаление дубликатов
unique_values = set(df['category'])
df_unique = df[df['category'].isin(unique_values)]

# Быстрая проверка
valid_categories = {'A', 'B', 'C'}
df_filtered = df[df['category'].isin(valid_categories)]  # O(n)

# Пересечение категорий
train_categories = set(df_train['category'].unique())
test_categories = set(df_test['category'].unique())
common_categories = train_categories & test_categories

6. Очередь (Queue)

Когда применяю:

  • Обработка данных потоком (streaming)
  • BFS при поиске (Graph algorithms)
  • Batch processing

Пример:

from collections import deque

# Скользящее окно (sliding window)
window = deque(maxlen=30)  # Окно последних 30 дней
for value in time_series:
    window.append(value)
    rolling_mean = np.mean(window)
    # Вычисления на каждом шаге

# BFS для поиска в сети (граф пользователей)
queue = deque([start_user])
visited = set()
while queue:
    user = queue.popleft()
    if user not in visited:
        visited.add(user)
        for friend in get_friends(user):
            queue.append(friend)

7. Stack (Стек)

Когда применяю:

  • Парсинг данных
  • DFS алгоритмы
  • Отслеживание истории операций

Пример:

# DFS при анализе дерева (рекомендации, иерархии)
from collections import defaultdict

def dfs_traverse(node, graph, visited, stack):
    visited.add(node)
    stack.append(node)
    for neighbor in graph[node]:
        if neighbor not in visited:
            dfs_traverse(neighbor, graph, visited, stack)

# История транформаций
transform_stack = []
transform_stack.append(('normalize', X_train))
transform_stack.append(('pca', X_pca))
X_current = transform_stack[-1][1]  # Последняя трансформация

8. Heap (Приоритетная очередь)

Когда применяю:

  • K-nearest neighbors (KNN)
  • Top-K элементов
  • Алгоритмы на графах (Dijkstra)
  • Выбор важных фич

Пример:

import heapq

# Top-K признаков по важности
feature_importance = {'age': 0.3, 'income': 0.25, 'score': 0.2}
top_k = heapq.nlargest(2, feature_importance.items(), key=lambda x: x[1])
print(top_k)  # [('age', 0.3), ('income', 0.25)]

# K ближайших соседей (манипуляция)
from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors=5)
knn.fit(X_train, y_train)
predictions = knn.predict(X_test)

9. Hash Table / Dict для кэширования

Когда применяю:

  • Кэширование дорогих вычислений
  • Memoization при рекурсии
  • Быстрая валидация данных

Пример:

from functools import lru_cache

# Кэширование результатов функции
@lru_cache(maxsize=128)
def encode_category(category):
    # Дорогое вычисление
    return category_to_embedding[category]

# Ручное кэширование
cache = {}
for value in df['category']:
    if value not in cache:
        cache[value] = expensive_encoding(value)
    encoded = cache[value]

10. Graph (Граф) — для рекомендаций

Когда применяю:

  • Системы рекомендаций (матрица сходства)
  • Анализ сетей
  • Community detection
  • Знакомства между пользователями

Пример:

import networkx as nx
from scipy.sparse import csr_matrix

# Граф пользователей
G = nx.Graph()
for user1, user2 in user_connections:
    G.add_edge(user1, user2)

# Поиск соседей (рекомендации)
neighbors = list(G.neighbors(user_id))
recommendations = nx.common_neighbors(G, user_id, other_users)

# Матрица смежности
adjacency_matrix = nx.to_scipy_sparse_array(G)

11. Sparse Matrix (разреженные матрицы)

Когда применяю:

  • NLP (bag of words, TF-IDF)
  • One-hot encoding категорий
  • Большие матрицы с много нулей

Пример:

from sklearn.feature_extraction.text import TfidfVectorizer
from scipy.sparse import csr_matrix

# TF-IDF для текстов
vectorizer = TfidfVectorizer(max_features=1000)
X_tfidf = vectorizer.fit_transform(texts)  # Sparse matrix

# One-hot encoding
X_encoded = pd.get_dummies(df[['category', 'color']])  # Sparse

# Экономия памяти
print(X_tfidf.memory_usage())  # Гораздо меньше, чем dense

12. Time Series структуры

Когда применяю:

  • Временные ряды (ARIMA, Prophet)
  • Скользящие окна
  • Сезонность, тренды

Пример:

import pandas as pd
from statsmodels.tsa.arima.model import ARIMA

# DataFrame с временным индексом
ts_df = pd.DataFrame({
    'date': pd.date_range('2023-01-01', periods=100),
    'value': np.random.randn(100).cumsum()
})
ts_df.set_index('date', inplace=True)

# ARIMA модель
model = ARIMA(ts_df['value'], order=(1, 1, 1))
results = model.fit()
forecast = results.get_forecast(steps=10)

Матрица выбора структур по задачам

ЗадачаСтруктураПричина
Базовые вычисленияNumPy arrayСкорость, оптимизация
EDA, очисткаDataFrameГибкость, удобство
Категоричные признакиDict/SetБыстрый поиск, кэширование
Текст (NLP)Sparse matrixЭкономия памяти
Временные рядыTimeSeries (DataFrame)Индексирование по времени
РекомендацииGraph/MatrixСвязи между объектами
Top-KHeapO(n log k) вместо O(n log n)

Практический совет

В production pipeline я обычно использую комбинацию:

1. Pandas DataFrame → загрузка и очистка
2. NumPy array → нормализация и фич-инжиниринг
3. Sparse matrix → передача в модель (если нужно)
4. Словарь → кэширование и конфигурация
5. Граф → для рекомендаций и анализа связей

Итог: Выбор структуры данных зависит от:

  • Операции, которые нужно выполнять (доступ, поиск, вставка)
  • Размер данных (памяти и скорость)
  • Тип данных (числа, категории, текст, временные ряды)
  • Требования к производительности (O-нотация)

Опыт показывает, что комбинированный подход (Pandas + NumPy + Sparse + Graph) охватывает 95% реальных задач Data Science.

Какие структуры данных знаешь и когда их применяешь? | PrepBro