matplotlib ecdfplot可以显示变量的浓度吗?例如,前10项占总数的20%,等等

2lpgd968  于 2023-05-01  发布在  其他
关注(0)|答案(1)|浏览(99)

问题

我想创建一个图表来显示浓度由某个变量。假设我有一个一维价格数组。

*我想要一个图,显示前10个最昂贵的项目占总价的10%,前100个最昂贵的项目占总价的40%,等等。

  • 这在我们想要了解某些数据的集中程度或不集中程度的所有情况下都很有用:例如,很少的借款人占银行的大部分风险,在给定时期内很少的几天占大部分降雨量,等等。

我所做的一切
我手动按价格排序,计算累计和,除以总价格并绘制。

为什么不理想

我想使用SeaBorn的displot和facetgrids来计算多个类别的数据。就像这样:

问题

有没有办法使用ecdfplot或其他与seaborn的displot兼容的函数?

我的代码(运行正常但不理想)

import numpy as np
from numpy.random import default_rng
import pandas as pd
import copy

import matplotlib
matplotlib.use('TkAgg', force = True)
import matplotlib.pyplot as plt

import seaborn as sns
import seaborn.objects as so
from matplotlib.ticker import FuncFormatter
sns.set_style("darkgrid")
rng = default_rng()

# I generate random samples from a truncated normal distr
# (I don't want negative values)
n = int(2e3)
n_red = int(n/3)
n_green = n - n_red
df = pd.DataFrame()
df['price']= np.random.randn(n) * 100 + 20
df['colour'] = np.hstack([np.repeat('red',n_red),
                          np.repeat('green', n_green)])
df = copy.deepcopy(df.query('price > 0')).reset_index(drop=True)

num_cols = len(np.unique(df['colour']))
fig1, ax1 = plt.subplots(num_cols)

sub_dfs={}
for my_ax, c in enumerate(np.unique(df['colour'])):
    sub_dfs[c] = copy.deepcopy(df.query('colour == @c'))
    sub_dfs[c] = sub_dfs[c].sort_values(by='price', ascending=False).reset_index()
    sub_dfs[c]['cum %'] = np.cumsum(sub_dfs[c]['price']) / sub_dfs[c]['price'].sum()

    sns.lineplot(sub_dfs[c]['cum %'], ax = ax1[my_ax])
    ax1[my_ax].set_title(c + ' - price concentration')
    ax1[my_ax].set_xlabel('# of items')
    ax1[my_ax].set_ylabel('% of total price')

我试过但不起作用

我已经使用了displotecdf

fig2 = sns.displot(kind='ecdf', data = df, y='price', col='colour', col_wrap =2, weights ='price',
                   facet_kws=dict(sharey=False))

fig3 = sns.displot(kind='ecdf', data = df, x='price', col='colour', col_wrap =2, weights='price',
                   facet_kws=dict(sharey=False))

编辑:Mwascom的回答(我还是不能让它工作)

@mwaskom,谢谢你的回答。但是,我担心我还是做错了什么,因为我没有得到想要的结果。
如果我跑步:

fig5 = sns.displot(kind='ecdf', data=df, x=df.index, col='colour', col_wrap =2, weights='price',
                   facet_kws=dict(sharey=False, sharex=False))

1.我得到了两条直线,而我需要的图是凸的(见顶部的第一个图)。直线表示价格平均分配,即10%的项目占总价格的10%。凸函数意味着前10%的项目占总价格的10%以上(这是我的情况)。我得到的是这个:

1.在我的玩具示例中,我有一个ca的类别。400个项目和一个与ca。由于X轴是整个 Dataframe 的索引,因此第二曲线图从400到1,200,而不是从1到800。

ehxuflar

ehxuflar1#

如果我理解正确的话,你可以使用带权重的ECDF来实现:

df = (
    sns.load_dataset("diamonds")
    .sort_values("price", ascending=False)
    .reset_index(drop=True)
    .rename_axis("item")
)
sns.displot(df, x="item", weights="price", kind="ecdf")

相关问题