У меня есть кадр данных, который я хочу разбить (т.е. сгруппировать в поддиапазоны) по одному столбцу и взять среднее значение второго столбца для каждого из ящиков:
import pandas as pd
import numpy as np
data = pd.DataFrame(columns=['Score', 'Age'])
data.Score = [1, 1, 1, 1, 0, 1, 2, 1, 0, 1, 1, 0, 2, 1, 1, 2, 1, 0, 1, 1, -1, 1, 0, 1, 1, 0, 1, 0, -2, 1]
data.Age = [29, 59, 44, 52, 60, 53, 45, 47, 57, 54, 35, 32, 48, 31, 49, 43, 67, 32, 31, 42, 37, 45, 52, 59, 56, 57, 48, 45, 56, 31]
_, bins = np.histogram(data.Age, 10)
labels = ['{}-{}'.format(i + 1, j) for i, j in zip(bins[:-1], bins[1:])]
labels[0] = '{}-{}'.format(bins[0], bins[1])
binned = pd.cut(data.Age, bins=bins, labels=labels, include_lowest=True, precision=0)
df = data.groupby(binned)['Score'].mean().reset_index()
df
Есть 2 проблемы с этим биннингом:
- существует разрыв 1 между верхней границей
(n-1)
th бина и нижней границейn
th бина (это означает, что группирование не является непрерывным, и точки данных, лежащие в этом промежутке, пропускаются). - последние несколько пределов бина имеют много цифр после запятой. Я использовал флаг
precision=0
вcut
, но, похоже, он бесполезен - независимо от того, какойx
я использую вprecision=x
, он все равно создает ячейки с несколькими последними ячейками, имеющими много цифр после запятой.
Второй пункт вызывает проблемы, когда, например, я пытаюсь построить df
, где он портит вид оси X:
import matplotlib.pyplot as plt
plt.plot([str(i) for i in df.Age], df.Score, 'o-')
Почему это происходит, несмотря на флаг precision=0
, который я поставил, чтобы указать, что я хочу использовать только целые числа в качестве пределов корзины, а не числа с плавающей запятой? И как мне это исправить?
Я временно решаю эту проблему, вручную конвертируя значения bin в int
s:
_, bins = np.histogram(data.Age, 10)
for i in range(len(bins)): # my fix
bins[i] = int(bins[i])
labels = ['{}-{}'.format(i + 1, j) for i, j in zip(bins[:-1], bins[1:])]
labels[0] = '{}-{}'.format(bins[0], bins[1])
binned = pd.cut(data.Age, bins=bins, labels=labels, include_lowest=True, precision=0)
df = data.groupby(binned)['Score'].mean().reset_index()
df
Но это похоже на взлом, и я думаю, что у него должно быть «правильное» решение, а не хакерское исправление. И хотя это устранило вторую проблему, я не уверен, что это устранит первую проблему.