Эффективный способ: как посчитать количество значений в столбце pandas

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Для кого эта статья:

  • начинающие и опытные дата-сайентисты
  • разработчики, работающие с Python и pandas
  • специалисты, заинтересованные в оптимизации работы с большими данными

    Работа с данными в pandas требует точности и скорости, особенно когда речь идёт о таком фундаментальном действии, как подсчёт значений в столбцах. Эта операция кажется элементарной, но при работе с миллионами записей или сложными мультииндексными структурами может превратиться в настоящий вызов. Разница между оптимальным и неоптимальным подходом к подсчёту значений может измеряться не просто секундами, а минутами или даже часами вычислительного времени. Давайте разберёмся, как опытные дата-сайентисты делают это эффективно. 📊

Хотите освоить продвинутые техники работы с данными в Python? Курс «Python-разработчик» с нуля от Skypro — это идеальное решение для тех, кто стремится овладеть инструментами анализа данных. Вы не только научитесь эффективно работать с библиотекой pandas и подсчитывать значения в столбцах разными способами, но и освоите весь стек технологий, необходимый современному Python-разработчику. От базовых операций до сложных алгоритмов — всё в одном курсе!

Основные методы подсчета количества значений в столбцах pandas

Pandas предлагает несколько элегантных методов для подсчёта значений, каждый из которых имеет свои преимущества в зависимости от контекста задачи. Знание этих инструментов и понимание, когда какой применять — отличает новичка от опытного аналитика. 🧠

МетодОписаниеОптимальное применение
value_counts()Подсчитывает уникальные значения и их частотуКатегориальные данные, анализ распределений
count()Подсчитывает непустые (не-NaN) значенияПроверка полноты данных, без учёта типов значений
len()Возвращает длину объектаПодсчёт всех строк, включая пустые значения
nunique()Подсчитывает количество уникальных значенийАнализ кардинальности данных
sizeАтрибут, возвращающий количество элементовБыстрый подсчёт для Series или DataFrame

Для базового подсчёта ненулевых значений в столбце использую метод count():

Python
Скопировать код
import pandas as pd

# Создаем тестовый DataFrame
df = pd.DataFrame({
'category': ['A', 'B', 'A', None, 'B', 'C', 'C'],
'value': [1, 2, 3, np.nan, 5, 6, 7]
})

# Подсчет ненулевых значений
non_null_count = df['category'].count()
print(f"Количество ненулевых значений: {non_null_count}") # Выведет: 6

Если же нужно узнать общее количество элементов, включая пустые значения, более эффективно использовать len() или атрибут size:

Python
Скопировать код
# Общее количество элементов (включая NaN)
total_count = len(df['category'])
# Или
total_count = df['category'].size

print(f"Общее количество элементов: {total_count}") # Выведет: 7

Для определения количества уникальных значений используйте nunique():

Python
Скопировать код
# Подсчет уникальных значений
unique_count = df['category'].nunique()
print(f"Количество уникальных значений: {unique_count}") # Выведет: 3

Алексей Морозов, Lead Data Scientist

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

Например, мы обнаружили, что для проверки процента пропущенных значений гораздо эффективнее использовать:

Python
Скопировать код
missing_percentage = df['transaction_id'].isna().mean() * 100

вместо:

Python
Скопировать код
missing_percentage = (len(df) – df['transaction_id'].count()) / len(df) * 100

При работе с датасетом в 20 миллионов строк такая оптимизация сократила время выполнения с 38 секунд до менее чем 3 секунды. Правильный выбор метода — не просто элегантность кода, это драгоценное рабочее время.

Важно понимать разницу между количеством всех значений и непустых значений. Например, при вычислении средних значений или других статистик, pandas автоматически исключает NaN значения, что может привести к неожиданным результатам, если вы не учитываете этот факт.

Кинга Идем в IT: пошаговый план для смены профессии

Функция value_counts(): подробный анализ частоты значений

value_counts() — настоящая швейцарская армейская пила для анализа распределения значений в столбцах. Эта функция подсчитывает частоту уникальных значений и возвращает сортированную Series, где индексы — уникальные значения, а значения — их количество. 📈

Python
Скопировать код
# Базовое использование value_counts()
category_counts = df['category'].value_counts()
print(category_counts)
# Вывод:
# C 2
# B 2
# A 2
# Name: category, dtype: int64

Функция value_counts() имеет множество полезных параметров, которые значительно расширяют её возможности:

  • normalize: возвращает относительные частоты (доли) вместо абсолютных значений
  • sort: сортирует результаты по частоте (по умолчанию True)
  • ascending: меняет порядок сортировки (по умолчанию False)
  • dropna: исключает NaN значения из подсчета (по умолчанию True)
  • bins: группирует числовые данные по бинам
Python
Скопировать код
# Относительные частоты
relative_freq = df['category'].value_counts(normalize=True)
print(relative_freq)
# Вывод:
# C 0.333333
# B 0.333333
# A 0.333333
# Name: category, dtype: float64

# Включение NA-значений в подсчет
with_na = df['category'].value_counts(dropna=False)
print(with_na)
# Вывод:
# C 2
# B 2
# A 2
# NaN 1
# Name: category, dtype: int64

# Сортировка по возрастанию
asc_counts = df['category'].value_counts(ascending=True)
print(asc_counts)
# Вывод:
# A 2
# B 2
# C 2
# Name: category, dtype: int64

Для числовых данных особенно полезна возможность группировки по интервалам с помощью параметра bins:

Python
Скопировать код
# Создаем числовой ряд
import numpy as np
numeric_series = pd.Series(np.random.normal(size=1000))

# Группируем по интервалам
binned_counts = numeric_series.value_counts(bins=10)
print(binned_counts)

Комбинирование value_counts() с другими методами pandas открывает еще больше возможностей для анализа:

Python
Скопировать код
# Подсчет частоты по двум столбцам
combined_counts = df.groupby(['category', 'value']).size()
print(combined_counts)

# Подсчет с фильтрацией
filtered_counts = df[df['value'] > 3]['category'].value_counts()
print(filtered_counts)
ЗадачаКодПримечание
Базовый подсчетdf['column'].value_counts()Стандартный подсчет частот
Процентное соотношениеdf['column'].value_counts(normalize=True) * 100Удобно для отчетов
Включая пустые значенияdf['column'].value_counts(dropna=False)Важно для анализа качества данных
По интерваламdf['numeric_column'].value_counts(bins=10)Для непрерывных числовых данных
По категориям с условиемdf[df['filter'] > value]['column'].value_counts()Для сегментированного анализа

Оптимизация подсчета в больших датасетах pandas

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

Одна из ключевых оптимизаций — категориальные типы данных. Для строковых столбцов с повторяющимися значениями преобразование в категориальный тип может значительно ускорить подсчеты:

Python
Скопировать код
# Преобразуем в категориальный тип
df['category'] = df['category'].astype('category')

# Теперь подсчет будет выполняться быстрее
cat_counts = df['category'].value_counts()

Для действительно больших наборов данных можно использовать параметр nlargest или nsmallest для получения только топовых категорий:

Python
Скопировать код
# Получаем только 5 наиболее частых категорий
top_categories = df['category'].value_counts().nlargest(5)
print(top_categories)

Если датасет не помещается в память, стоит обратиться к библиотекам для работы с большими данными:

Python
Скопировать код
# Пример с использованием dask для больших данных
import dask.dataframe as dd

# Загружаем данные с использованием dask
ddf = dd.read_csv("huge_data.csv")

# Подсчет значений
category_counts = ddf['category'].value_counts().compute()

Для экстремально больших наборов данных хороший подход — использование агрегирующих SQL-запросов, если данные хранятся в базе:

Python
Скопировать код
import pandas as pd
from sqlalchemy import create_engine

# Подключаемся к БД
engine = create_engine('postgresql://username:password@localhost:5432/mydatabase')

# Выполняем агрегирующий запрос
query = """
SELECT category, COUNT(*) as count 
FROM big_table 
GROUP BY category
ORDER BY count DESC
"""

# Получаем результаты прямо в pandas
result = pd.read_sql(query, engine)
print(result)

Михаил Верещагин, Data Engineering Lead

Когда я работал над проектом по анализу поведения пользователей e-commerce платформы, мы столкнулись с серьезной проблемой производительности. Нам нужно было ежедневно обрабатывать лог событий размером более 50 ГБ и подсчитывать частоту действий пользователей по различным категориям.

Изначально мой коллега использовал стандартный подход:

Python
Скопировать код
user_actions = df['action_type'].value_counts()

На обработку уходило почти 45 минут, что было неприемлемо для ежедневного отчета.

Мы оптимизировали процесс в несколько этапов:

  1. Сначала перевели строковые столбцы в категориальный тип
  2. Затем разделили большой файл на чанки и обрабатывали их параллельно
  3. Наконец, применили предварительную фильтрацию данных

Конечный код выглядел так:

Python
Скопировать код
# Разбиваем на чанки и параллельно обрабатываем
reader = pd.read_csv('huge_log.csv', chunksize=1_000_000)
results = pd.Series(dtype='int64')

for chunk in reader:
# Конвертируем в категории для экономии памяти и ускорения
chunk['action_type'] = chunk['action_type'].astype('category')
# Только интересующие нас действия
filtered = chunk[chunk['timestamp'] >= yesterday]
# Агрегируем результаты
counts = filtered['action_type'].value_counts()
results = results.add(counts, fill_value=0)

final_counts = results.astype('int64')

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

Визуализация результатов подсчета значений в столбцах

После подсчета значений важно представить результаты наглядно. pandas отлично интегрируется с популярными библиотеками визуализации такими как matplotlib и seaborn. 📊

Базовый подход к визуализации частотности значений полученных через value_counts():

Python
Скопировать код
import matplotlib.pyplot as plt
import seaborn as sns

# Подсчитываем частоту категорий
category_counts = df['category'].value_counts()

# Создаем базовый bar plot
category_counts.plot(kind='bar')
plt.title('Распределение категорий')
plt.ylabel('Количество')
plt.xlabel('Категории')
plt.show()

Для более сложных визуализаций можно использовать seaborn:

Python
Скопировать код
# Используем seaborn для более продвинутой визуализации
plt.figure(figsize=(10, 6))
sns.countplot(x='category', data=df, palette='viridis')
plt.title('Распределение категорий (Seaborn)')
plt.ylabel('Количество')
plt.show()

Для сравнения распределения нескольких групп можно использовать группировку:

Python
Скопировать код
# Создадим дополнительную категориальную переменную для примера
df['size'] = ['Small', 'Medium', 'Large', 'Small', 'Medium', 'Large', 'Small']

# Визуализируем распределение категорий по размеру
plt.figure(figsize=(12, 6))
sns.countplot(x='category', hue='size', data=df, palette='Set2')
plt.title('Распределение категорий по размеру')
plt.ylabel('Количество')
plt.show()

Интерактивные визуализации с plotly делают анализ еще удобнее:

Python
Скопировать код
import plotly.express as px

# Создаем интерактивную столбчатую диаграмму
fig = px.bar(
x=category_counts.index,
y=category_counts.values,
labels={'x': 'Категория', 'y': 'Количество'},
title='Распределение категорий (интерактивно)'
)
fig.show()

Для долевого распределения хорошо подходят круговые диаграммы:

Python
Скопировать код
# Подсчитываем относительные частоты
relative_counts = df['category'].value_counts(normalize=True)

# Создаем круговую диаграмму
plt.figure(figsize=(8, 8))
plt.pie(
relative_counts.values, 
labels=relative_counts.index, 
autopct='%1.1f%%', 
startangle=90,
shadow=True
)
plt.title('Процентное соотношение категорий')
plt.axis('equal') # Equal aspect ratio ensures that pie is drawn as a circle
plt.show()

И наконец, для визуализации трендов во временных рядах хорошо работает подсчёт по временным интервалам:

Python
Скопировать код
# Создадим временной ряд
dates = pd.date_range(start='2025-01-01', periods=100, freq='D')
df_time = pd.DataFrame({
'date': dates,
'event': np.random.choice(['A', 'B', 'C'], size=100)
})

# Группируем по месяцам и подсчитываем события
monthly_counts = df_time.groupby([df_time['date'].dt.month, 'event']).size().unstack()

# Визуализация трендов
monthly_counts.plot(kind='line', marker='o', figsize=(12, 6))
plt.title('Месячная динамика событий')
plt.xlabel('Месяц')
plt.ylabel('Количество событий')
plt.grid(True, linestyle='--', alpha=0.7)
plt.show()

Автоматизация процесса подсчета для множества столбцов

При работе с реальными наборами данных часто требуется проанализировать десятки или сотни столбцов. Ручной подсчет для каждого из них непрактичен. Здесь на помощь приходит автоматизация. 🤖

Создадим функцию для автоматического подсчета и анализа всех категориальных столбцов в датафрейме:

Python
Скопировать код
def analyze_categorical_columns(df, top_n=5, plot=False, figsize=(15, 10)):
"""
Анализирует все категориальные столбцы датафрейма

Parameters:
-----------
df : pandas.DataFrame
Анализируемый датафрейм
top_n : int
Число наиболее частых категорий для отображения
plot : bool
Создавать ли визуализации
figsize : tuple
Размер итогового графика

Returns:
--------
dict
Словарь с результатами анализа для каждого столбца
"""
# Определяем категориальные столбцы
cat_columns = df.select_dtypes(include=['object', 'category']).columns

if len(cat_columns) == 0:
print("Категориальные столбцы не найдены")
return {}

results = {}

for col in cat_columns:
# Подсчет значений
value_counts = df[col].value_counts()
unique_count = df[col].nunique()
null_count = df[col].isna().sum()
null_percent = null_count / len(df) * 100

# Сохраняем результаты
results[col] = {
'unique_count': unique_count,
'null_count': null_count,
'null_percent': null_percent,
'top_values': value_counts.nlargest(top_n)
}

# Создаем визуализацию, если требуется
if plot:
plt.figure(figsize=(figsize[0] // len(cat_columns), figsize[1]))
value_counts.nlargest(top_n).plot(kind='bar', title=f'Top {top_n} values in {col}')
plt.xticks(rotation=45, ha='right')
plt.tight_layout()
plt.show()

return results

# Пример использования
analysis_results = analyze_categorical_columns(df, plot=True)
print(analysis_results)

Для более глубокого анализа можно создать функцию, которая генерирует полный отчет по всем столбцам датафрейма:

Python
Скопировать код
def generate_dataframe_report(df, save_to_file=False, filename='dataframe_report.html'):
"""
Генерирует полный отчет по всем столбцам датафрейма

Parameters:
-----------
df : pandas.DataFrame
Анализируемый датафрейм
save_to_file : bool
Сохранять ли отчет в HTML-файл
filename : str
Имя файла для сохранения отчета

Returns:
--------
pandas.DataFrame
Датафрейм с результатами анализа
"""
report = []

# Проходим по всем столбцам
for column in df.columns:
column_type = df[column].dtype

# Базовые метрики для всех типов
metrics = {
'column_name': column,
'dtype': str(column_type),
'count': df[column].count(),
'null_count': df[column].isna().sum(),
'null_percent': round(df[column].isna().mean() * 100, 2),
'unique_count': df[column].nunique()
}

# Специфические метрики для числовых столбцов
if np.issubdtype(column_type, np.number):
metrics.update({
'min': df[column].min(),
'max': df[column].max(),
'mean': df[column].mean(),
'median': df[column].median(),
'std': df[column].std()
})

# Топ-3 наиболее частых значения
value_counts = df[column].value_counts().nlargest(3)
for i, (value, count) in enumerate(value_counts.items(), 1):
metrics[f'top{i}_value'] = value
metrics[f'top{i}_count'] = count

# Специфические метрики для категориальных столбцов
else:
# Добавляем только длину строки для строковых значений
if df[column].dtype == 'object':
metrics['avg_length'] = df[column].str.len().mean()

# Топ-3 наиболее частых категорий
value_counts = df[column].value_counts().nlargest(3)
for i, (value, count) in enumerate(value_counts.items(), 1):
metrics[f'top{i}_value'] = value
metrics[f'top{i}_count'] = count
metrics[f'top{i}_percent'] = round(count / len(df) * 100, 2)

report.append(metrics)

# Создаем датафрейм отчета
report_df = pd.DataFrame(report)

# Сохраняем в HTML при необходимости
if save_to_file:
report_df.to_html(filename, index=False)
print(f"Отчет сохранен в {filename}")

return report_df

# Пример использования
report_df = generate_dataframe_report(df, save_to_file=True)
display(report_df)

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

Python
Скопировать код
# Пример автоматизированного процесса с использованием функций выше
import schedule
import time
from datetime import datetime

def daily_data_analysis():
"""Ежедневный анализ данных"""
print(f"Запуск анализа данных: {datetime.now()}")

# Загрузка свежих данных
df = pd.read_csv('path_to_your_data.csv')

# Генерация отчета
report_date = datetime.now().strftime('%Y%m%d')
report_df = generate_dataframe_report(
df, 
save_to_file=True, 
filename=f'report_{report_date}.html'
)

# Дополнительный анализ категориальных столбцов
cat_analysis = analyze_categorical_columns(df, plot=True)

# Можно добавить отправку результатов по email
# send_email_report(report_df, cat_analysis)

print(f"Анализ данных завершен: {datetime.now()}")

# Настройка расписания (запуск каждый день в 8:30)
schedule.every().day.at("08:30").do(daily_data_analysis)

# Для демонстрации запустим один раз
daily_data_analysis()

# Для постоянной работы планировщика раскомментируйте код ниже
# while True:
# schedule.run_pending()
# time.sleep(60)

Готовы изменить свою карьеру и стать востребованным IT-специалистом? Хотите не только анализировать данные, но и создавать полноценные приложения на Python? Тест на профориентацию от Skypro поможет вам определить, подходит ли вам карьера в аналитике данных или Python-разработке. Узнайте свои профессиональные склонности, сильные стороны и оптимальную карьерную траекторию всего за несколько минут. Результаты теста дадут вам ясное понимание, стоит ли углубляться в работу с pandas и анализ данных!

Умение эффективно обрабатывать данные в pandas становится критически важным навыком в эпоху информационного взрыва. Правильно посчитанные значения в столбцах — это фундамент точного анализа и надежных выводов. Методы, описанные в этой статье, позволят вам оптимизировать рабочие процессы, сэкономить вычислительные ресурсы и время. Помните: разница между хорошим и выдающимся специалистом по данным часто заключается в глубоком понимании инструментов, которыми он пользуется. Применяйте эти техники в своих проектах, экспериментируйте с различными подходами и следите за производительностью кода — это путь к мастерству в анализе данных.