Фильтрация чисел в Pandas: как получать только числовые данные
Фильтрация чисел в Pandas: основные подходы
Как отфильтровать строки DataFrame, оставив только те, которые можно интерпретировать как числа?
Наиболее универсальный способ - использовать функцию pd.to_numeric с параметром errors='coerce'. Она пытается преобразовать каждый элемент в число, а при неудаче заменяет его на NaN. Затем можно отфильтровать строки, где результат не равен NaN, с помощью .notna().
import pandas as pd
df = pd.DataFrame({'data': ['123', 'abc', '45.6', '7e2', '']})
mask = pd.to_numeric(df['data'], errors='coerce').notna()
filtered = df[mask]
print(filtered)обработка больших данных python (обработка больших данных в python)
data 0 123 2 45.6 3 7e2
очистка данных python (очистка данных в python)
Такой подход корректно обрабатывает целые числа, числа с плавающей точкой, научную нотацию и игнорирует нечисловые строки. Это решение рекомендуется для большинства задач очистки данных.
Как выбрать только числовые столбцы в DataFrame?
Метод DataFrame.select_dtypes(include=['number']) возвращает подмножество столбцов, которые имеют числовой тип (int, float, complex). Это полезно для анализа больших таблиц, где нужно работать исключительно с числами.
df = pd.DataFrame({'A': [1, 2], 'B': ['x', 'y'], 'C': [3.0, 4.0]})
numeric_cols = df.select_dtypes(include='number')
print(numeric_cols)
Python подготовка данных (подготовка данных в python)
A C 0 1 3.0 1 2 4.0
работа с dataframe python (работа с dataframe в python)
Обратите внимание: столбцы с типом object, даже если они содержат числа, не попадут в выборку.
Как проверить, является ли значение числом, без Pandas?
Если данные находятся в обычном списке, можно использовать встроенную функцию isinstance() или метод строк str.isdigit() (только для целых положительных). Для более точной проверки применяют регулярные выражения.
import re
data = ['123', '-45.6', 'abc', '1e2', '']
def is_number(s):
try:
float(s)
return True
except ValueError:
return False
numbers = [x for x in data if is_number(x)]
print(numbers)Python работа с большими данными (работа с большими данными в python)
['123', '-45.6', '1e2']
структурированные данные python (структурированные данные в python)
Вариант с try/except надёжен, но может быть медленным на больших наборах.
Как отфильтровать числа, записанные с разделителями тысяч или в разных форматах?
Используйте pd.to_numeric с параметром errors='coerce' после предварительной очистки строк (удаление пробелов, замена запятых).
series = pd.Series(['1,234', '5.678', '12,345.67', 'abc'])
cleaned = series.str.replace(',', '')
numeric = pd.to_numeric(cleaned, errors='coerce').notna()
print(series[numeric])генерация данных python (генерация данных в python)
0 1,234 1 5.678 2 12,345.67 dtype: object
После фильтрации потребуется конвертировать строки в числовой тип.
Типичные ошибки и их решения
- Ошибка: pd.to_numeric возвращает NaN для значений, которые выглядят как числа, но имеют лишние символы (пробелы, знаки валют). Решение: предварительно очистить строки с помощью str.strip() и str.replace().
- Ошибка: Метод str.isdigit() не распознаёт отрицательные числа или числа с плавающей точкой. Решение: использовать pd.to_numeric или регулярное выражение r'^-?\d+(\.\d+)?([eE][+-]?\d+)?$'.
- Ошибка: При фильтрации строк по маске .notna() теряются индексы. Решение: сохранять исходный индекс с помощью reset_index(drop=True) при необходимости.
- Ошибка: Столбец содержит смесь типов (int и str). Решение: перед проверкой преобразовать весь столбец в строковый тип через astype(str).
Расширенные примеры фильтрации чисел
Пример 1: Фильтрация с помощью регулярных выражений
import pandas as pd
import re
df = pd.DataFrame({'raw': ['$1,200.50', '25%', '3.14', 'some text', '-0.001']})
pattern = r'^-?\$?\d{1,3}(,\d{3})*(\.\d+)?%?$'
def is_numeric_advanced(s):
return bool(re.match(pattern, s))
mask = df['raw'].apply(is_numeric_advanced)
print(df[mask])
raw 0 $1,200.50 1 25% 2 3.14 4 -0.001
Регулярное выражение учитывает доллары, проценты и запятые в тысячах. Однако такой подход требует точной настройки под формат данных.
Пример 2: Отбор числовых колонок по dtype и конвертация
df = pd.DataFrame({
'id': [1, 2],
'value': [10.5, 20.3],
'category': ['A', 'B'],
'code': ['101', '202']
})
# Выбрать числовые колонки
numeric_df = df.select_dtypes(include=['int64', 'float64'])
print(numeric_df.dtypes)
# Принудительная конвертация строкового столбца 'code' в числа
numeric_df['code'] = pd.to_numeric(df['code'], errors='coerce')
print(numeric_df)
id int64 value float64 dtype: object id value code 0 1 10.5 101 1 2 20.3 202
Обратите внимание: столбец 'category' не попал в выборку. Добавление 'code' произошло после конвертации – важно следить за типом исходных данных.
Пример 3: Фильтрация с учётом NaN и None
import numpy as np
df = pd.DataFrame({'col': [1, 'two', np.nan, None, '3.0', 'NaN']})
# Способ 1: pd.to_numeric
mask1 = pd.to_numeric(df['col'], errors='coerce').notna()
print('Способ 1:', df[mask1])
# Способ 2: проверка на число + исключение NaN
def is_num(x):
try:
float(x)
return True
except (ValueError, TypeError):
return False
mask2 = df['col'].apply(is_num)
print('Способ 2:', df[mask2])
Способ 1: col 0 1 3 NaN # !!! NaN интерпретирован как число Способ 2: col 0 1 4 3.0
Первый способ считает NaN числом (так как float('nan') не вызывает ошибки). Второй способ через float(x) также допускает NaN, но при использовании np.nan в строке возникает TypeError – поэтому None отсекается. Для исключения NaN нужно добавить проверку not np.isnan(x).
Пример 4: Использование np.isnan для чистки результата
series = pd.Series([1, 2, np.nan, 4, None, '5'])
numeric = pd.to_numeric(series, errors='coerce')
mask = numeric.notna() & ~np.isnan(numeric)
# Или короче: mask = numeric.apply(lambda x: not np.isnan(x))
print('Числа без NaN:', series[mask])
Числа без NaN: 0 1 1 2 3 4 5 5 dtype: object
Но обычно NaN в результате преобразования не мешает – если нужно исключить исходные NaN, лучше проверять исходную серию.
Пример 5: Многоуровневая фильтрация (числа + положительные)
df = pd.DataFrame({'val': ['-5', '0', '3.14', 'abc', '100']})
numeric_mask = pd.to_numeric(df['val'], errors='coerce').notna()
positive_mask = pd.to_numeric(df['val'], errors='coerce') >= 0
filtered = df[numeric_mask & positive_mask]
print(filtered)
val 1 0 2 3.14 4 100
Объединение масок позволяет гибко настраивать условия отбора.