Какие структуры данных знаешь и когда их применяешь?
Комментарии (2)
Ответ сгенерирован нейросетью и может содержать ошибки
Структуры данных в 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-K | Heap | O(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.