如何使用pandas hist批注三峰历史图?

时间:2019-04-01 14:09:18

标签: python plot histogram mode

我正在绘制数据框的一列作为历史图。当我绘制时,我可以看到有3个峰,所以它是三峰的。如何注释图表以标记每个峰的值?

下面的

我的代码并排绘制了两个直方图,第一个是具有异常值的数据场,第二个是不具有异常值的数据帧。

fig, ax = plt.subplots(ncols=2, figsize=(10,4))

df['price'].hist(bins=40,ax=ax[0])
df_nooutlier['price'].hist(bins=40,ax=ax[1])
df_nooutlier['price'].value_counts().head().plot(kind='line',linestyle='None', marker='o',color='r') #how can i plot such that i can see the labels 

我希望每个峰都用其频率标记

1 个答案:

答案 0 :(得分:1)

以下方法是查找模式及其索引(即x和y值以在其上绘制点和文本)。它使用np.histogram来获取与直方图相对应的分布计数和bin划分。

import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

def get_random_prices():
    """sample from three normal distributions"""
    dist1 = np.random.normal(loc=5, scale=.3, size=1000)
    dist2 = np.random.normal(loc=7, scale=.3, size=1000)
    dist3 = np.random.normal(loc=11, scale=.3, size=1000)
    min_price, max_price = 0, 20
    all_dist = np.concatenate([dist1, dist2, dist3])
    return all_dist[all_dist >= min_price][all_dist <= max_price]

def get_modes(counts, min_sep=.5):
    # simple method to get mode values and locations (indexes)
    # assume counts are already smoothed
    # assume last mode is not past penultimate spot
    modes = []
    max_ct = 0
    increasing = True
    for i, count in enumerate(counts[1:]):
        if count >= counts[i]:
            max_ct = count
            increasing = True
        elif increasing:
            modes.append((max_ct, i))
            max_ct = 0
            increasing = False
    return modes

fig, ax = plt.subplots()

# create randomly generated data
df = pd.DataFrame({'price': get_random_prices()})

# get histogram data and display the same histogram
n_bins = 40
counts, divisions = np.histogram(df['price'], bins=n_bins)
df['price'].hist(bins=n_bins)

# find the peaks
modes = get_modes(counts)

# add the dots and labels for each peak, onto the histogram object
for mode, mode_index in modes:
    ax.plot(divisions[mode_index], mode, 'ro')
    # use offsets to make text appear away from the dots
    # probably write logic to determine this instead of hard-coding
    offset_x, offset_y = .1, 2
    ax.text(divisions[mode_index] + offset_x, mode + offset_y, mode, color='r')

以下显示的modes等于[(229, 5), (248, 15), (239, 35)],而np.__version__, pd.__version__('1.16.2', '0.24.2')

sample histogram