Python 如何使用分类变量按dataframe分组,以便在matplotlib中制作折线图?
我有产品交易历史的时间序列数据框,我需要制作折线图以查看产品发货人的成本趋势。为了绘制数据框架,我需要按分类变量营销阈值分组,并使用加权平均函数来平均成本阈值。我提出了加权平均函数,并试图将它们分组以生成绘图数据,但似乎我对数据进行了错误的操作,导致绘图数据框出现错误。我尝试使用apply函数pandas.groupby,但无法获得正确的结构化绘图数据?有人能给我指出一个可能的办法来纠正这个错误吗?有什么想法吗 我目前的尝试: 这是我的尝试,这是我的尝试:Python 如何使用分类变量按dataframe分组,以便在matplotlib中制作折线图?,python,pandas,matplotlib,data-manipulation,Python,Pandas,Matplotlib,Data Manipulation,我有产品交易历史的时间序列数据框,我需要制作折线图以查看产品发货人的成本趋势。为了绘制数据框架,我需要按分类变量营销阈值分组,并使用加权平均函数来平均成本阈值。我提出了加权平均函数,并试图将它们分组以生成绘图数据,但似乎我对数据进行了错误的操作,导致绘图数据框出现错误。我尝试使用apply函数pandas.groupby,但无法获得正确的结构化绘图数据?有人能给我指出一个可能的办法来纠正这个错误吗?有什么想法吗 我目前的尝试: 这是我的尝试,这是我的尝试: import pandas as pd
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
df = pd.read_csv('timeseries_df.csv', parse_dates=['date'])
# calculate comparable cost by using average threshold
def weighted_average(df, data_col, weight_col, by_col):
df['_data_times_weight'] = df[data_col] * df[weight_col]
df['_weight_where_notnull'] = df[weight_col] * pd.notnull(df[data_col])
g = df.groupby(by_col)
result = g['_data_times_weight'].sum() / g['_weight_where_notnull'].sum()
del df['_data_times_weight'], df['_weight_where_notnull']
return result
## for example, for Alpha Food Corps, all 50 threshold of protein with corresponding quantity_received, we'd get average threshold;
df_new = df.groupby(['dealer', 'threshold', 'protein_type'])['threshold']
df_new['avg_threshold'] = df_new.groupby(['dealer']).apply(wavg, "threshold", "quantity_received") ## some issue with this grouping
df_new['comparable_cost'] = df['price']*76/ df_new['avg_threshold']
基本上,我想通过使用阈值和接收的数量来找到平均阈值,高于加权平均值就可以做到这一点。但在我的尝试中,我绘制数据帧时出错了
例如,在我的示例dataframe中,我希望看到每个不同的经销商在一段时间内每个不同阈值的比例。要在折线图中查看经销商的成本动态,我需要找到每个经销商的平均阈值,然后找到其可比较的成本值作为新列。在理想的绘图数据框中,我希望看到所有经销商的成本动态,即价格、可比成本w.r.t每个阈值中的每种蛋白质类型沿时间序列。也许有更简单的方法来聚合我的数据帧并生成有意义的时间序列折线图。我愿意听取处理这个问题的可能方法和建议。谢谢
更新
在折线图中,我想看到每种蛋白质的比例是经销商成本动态的三倍。基本上,我想看看哪个经销商对市场的反应更好等等。有人能告诉我,用python处理这种EDA实践的最佳方法是什么吗?谢谢 1:df_new=df.groupby['dealer','threshold','protein_type']['threshold']
这一行是第一个问题。df_new是一个SeriesGroupBy对象
每组包含['dealer'、'threshold'、'protein_type'的['threshold']数据
每组看起来像:
嘉吉,50岁,鸡肉
1013 50
1056 50
1089 50
1161 50
1207 50
名称:阈值,数据类型:int64
2:df_new['avg_threshold']=df_new.groupby['dealer'].应用程序avg,阈值,接收数量
df_new.groupby['dealer']导致AttributeError:'SeriesGroupBy'对象没有属性'groupby'
这是因为df_new是一个系列,而不是一个数据帧
['dealer']在该系列中不存在
在加权_平均函数中,执行另一个groupby。
使用所有相关列更新初始groupby,以
df.groupby[“经销商”,“阈值”]
对于原始groupby,df_new['avg_threshold']=df_new.groupby['dealer']。applyAvg,threshold,quantity_received
换个新的。到df。
正确应用函数。应用平均值、阈值、接收数量
该函数是加权平均值,而不是wavg。
除了DataFrame之外,该函数还需要3个参数,但只提供了2个。
但是,我们将从函数中访问
更新后的groupby和函数调用将为:
dfg=df.groupby[‘经销商’,‘阈值’]。加权平均值,‘价格’,‘收到数量’
3.
a:更新def加权平均值
来自
按列移除,g=df.groupby按列移除
而不是将最终计算指定给结果并返回结果
将计算分配给df[“加权平均值”]
返回更新的数据帧和计算结果
使用平均阈值计算可比成本
def加权平均值DF、数据列、权重列:
df[''数据乘以权重']=df[数据列]*df[权重列]
df[''u-weight\u,其中\u-notnull']=df[weight\u col]*pd.notnulldf[data\u col]
df[“加权平均值”]=df[“数据乘以权重”].sum/df[“权重”[u其中不为空].sum
df=df.dropcolumns=[''数据乘以权重',''权重,其中不为空']
返回df
b:
这更干净
3a和3b产生相同的结果
def加权平均值组、价格、重量:
d=组[价格]
w=组[重量]
组['加权平均值']=d*w.sum/w.sum
返回组
4:更新代码
作为pd进口熊猫
读取数据
df=pd.read_csv'data/so_data/2020-08-03 63239708/mydf2.csv',parse_dates=['date']
使用平均阈值计算可比成本
def加权平均值DF、数据列、权重列:
df[''数据乘以权重']=df[数据列]*df[权重列]
df[''u-weight\u,其中\u-notnull']=df[weight\u col]*pd.notnulldf[data\u col]
df[“加权平均值”]=df[“数据乘以权重”].sum/df[“权重”[u其中不为空].sum
df=df.dropcolumns=[''数据乘以权重',''权重,其中不为空']
返回df
调用函数
dfg=df.groupby[‘经销商’,‘阈值’]。加权平均值,‘价格’,‘收到数量’
显示头
日期经销商阈值数量收到价格运费经销商交付成本Freshn
ess_天数蛋白质类型tot_距离目的地加权平均值
0 2017-12-22金州食品50 39037 0.5 0.07 0.6 3.39鸡肉901.0美国0.839475
1 2017-12-27金州食品85 35432 1.8 0.07 1.9 3.39牛肉901.0美国1.950728
2 2017-12-29金州食品50 32142 0.50.07 0.6 3.39鸡肉901.0美国0.839475
3 2017-12-30金州食品85 34516 1.8 0.07 1.9 3.39牛肉901.0美国1.950728
4 2018-01-02金州食品85 39930 1.8 0.07 1.9 3.39牛肉901.0美国1.950728
5:塑造数据框和绘图
作为pd进口熊猫
将matplotlib.pyplot作为plt导入
将matplotlib.dates导入为mdates
导入seaborn作为sns
从datetime导入timedelta,datetime
将阈值设置为类别
dfg.threshold=dfg.threshold.astype'category'
设置索引
dfg=dfg.set_索引['日期','经销商','蛋白质类型','阈值']
将数据帧形成长格式
dfl=dfg[['weighted_average','price']].stack.reset_index.renamecolumns={'level_4':'cats',0:'values'}
与所有经销商密谋
markers={price:s,加权平均值:X}
对于dfl.protein_type.unique中的pt:
对于dfl.threshold.unique中的t:
数据=dfl[dfl.protein_type==pt&dfl.threshold==t]
if not data.empty:对于某些阈值,没有数据
utc=lendata.threshold.unique
f、 axes=plt.subplotsnrows=utc,ncols=1,figsize=20,7,squence=False
对于UTC范围内的j:
p=sns.scatterplot'date','values',data=data,hue='dealer',markers=markers,style='cats',ax=axes[j,0]
p、 设置_titlef'阈值:{t}\n{pt}'
p、 设置_xlimdata.date.min-timedeltadays=60,data.date.max+timedeltadays=60
plt.Legendbox_to_anchor=1.04,0.5,loc=左中,borderaxespad=0
节目
与所有经销商的前两个地块
与单独的经销商密谋
在每组中,加权平均值为一个值。与其将其作为cats的一部分进行打印,不如使用
ud=dfl.DELER.unique
日期\最小值=dfl.date.min
日期=dfl.date.max
对于dfl.protein_type.unique中的pt:
对于dfl.threshold.unique中的t:
数据=dfl[dfl.protein_type==pt&dfl.threshold==t]
if not data.empty:对于某些阈值,没有数据
utc=lendata.threshold.unique
f、 axes=plt.subplotsnrows=utc,ncols=lenud,figsize=30,5,squence=False
对于UTC范围内的j:
就我而言,在列举中:
数据\u d=data[data.dealer==d]。排序\u值['cats','date']。重置\u indexdrop=True
价格=数据[data\u d.cats=='price']
w_avg=data_d[data_d.cats=='加权平均']
p=sns.scatterplot'date','values',data=price,hue='cats',ax=axs[j,i]
如果数据不为空:对于某些阈值,此循环中没有经销商d的数据
p、 hlinesw_avg['values'].unique.tolist、w_avg.date.min、w_avg.date.max、'orange',label='weighted avg'
p、 set_titlef'{d}\n保留:{t}\n{pt}'
p、 设置\u xlimdate\u min-timedeltadays=60,date\u max+timedeltadays=60
p、 legend.set_visibleFalse
labels=[datetime.fromordinalintv.strftime'%Y-%m-%d',用于p.getxticks中的v]
p、 设置xticklabelslabel,旋转=90
其他:
p、 set_titlef'{d}:无可用数据\n保留:{t}\n{pt}'
plt.Legendbox_至_锚=1.04,0.5,loc=左中,borderaxespad=0
节目
前几排
一列图
遍历蛋白质类型、阈值和值的每个唯一组合
up=dfl.protein_type.unique
ud=dfl.DELER.unique
ut=dfl.threshold.unique
日期\最小值=dfl.date.min
日期=dfl.date.max
年份\u fmt=mdate.DateFormatter“%Y-%m-%d”
对于pt in up:
对于ut中的th:
对于ud中的dl:
数据=dfl[dfl.protein_type==pt&dfl.threshold==th&dfl.dealer==dl]
if not data.empty:对于某些阈值,没有数据
价格=数据[data.cats=='price']
w_avg=数据[data.cats=='加权平均']
图,ax=plt.子图尺寸=8,5
p=sns.scatterplot'date','values',data=price,hue='cats',ax=ax
p、 hlinesw_avg['values'].unique.tolist、w_avg.date.min、w_avg.date.max、'orange',label='weighted avg'
p、 set_titlef'{dl}\n保留:{th}\n{pt}'
p、 设置\u xlimdate\u min-timedeltadays=60,date\u max+timedeltadays=120
p、 设置\u xticklabelsp.get\u xticks,旋转=90
p、 xaxis.set_major_formatteryears_fmt
plt.legendbox\u to\u anchor=1.04,0.5,loc='中间偏左',borderaxespad=0
节目
1:df_new=df.groupby['dealer','threshold','protein_type']['threshold']
这一行是第一个问题。df_new是一个SeriesGroupBy对象
每组包含['dealer'、'threshold'、'protein_type'的['threshold']数据
每组看起来像:
嘉吉,50岁,鸡肉
1013 50
1056 50
1089 50
1161 50
1207 50
名称:阈值,数据类型:int64
2:df_new['avg_threshold']=df_new.groupby['dealer'].应用程序avg,阈值,接收数量
df_new.groupby['dealer']导致AttributeError:'SeriesGroupBy'对象没有属性'groupby'
这是因为df_new是一个系列,而不是一个数据帧
['dealer']在该系列中不存在
在加权_平均函数中,执行另一个groupby。
使用所有相关列更新初始groupby,以
df.groupby[“经销商”,“阈值”]
对于原始groupby,df_new['avg_threshold']=df_new.groupby['dealer']。applyAvg,threshold,quantity_received
换个新的。到df。
正确应用函数。应用平均值、阈值、接收数量
该函数是加权平均值,而不是wavg。
除了DataFrame之外,该函数还需要3个参数,但只提供了2个。
但是,我们将从函数中访问
更新后的groupby和函数调用将为:
dfg=df.groupby[‘经销商’,‘阈值’]。加权平均值,‘价格’,‘收到数量’
3.
a:更新def加权平均值
来自
按列移除,g=df.groupby按列移除
而不是将最终计算指定给结果并返回结果
将计算分配给df[“加权平均值”]
返回更新的数据帧和计算结果
使用平均阈值计算可比成本
def加权平均值DF、数据列、权重列:
df[''数据乘以权重']=df[数据列]*df[权重列]
df[''u-weight\u,其中\u-notnull']=df[weight\u col]*pd.notnulldf[data\u col]
df[“加权平均值”]=df[“数据乘以权重”].sum/df[“权重”[u其中不为空].sum
df=df.dropcolumns=[''数据乘以权重',''权重,其中不为空']
返回df
b:
这更干净
3a和3b产生相同的结果
def加权平均值组、价格、重量:
d=组[价格]
w=组[重量]
组['加权平均值']=d*w.sum/w.sum
返回组
4:更新代码
作为pd进口熊猫
读取数据
df=pd.read_csv'data/so_data/2020-08-03 63239708/mydf2.csv',parse_dates=['date']
使用平均阈值计算可比成本
def加权平均值DF、数据列、权重列:
df[''数据乘以权重']=df[数据列]*df[权重列]
df[''u-weight\u,其中\u-notnull']=df[weight\u col]*pd.notnulldf[data\u col]
df[“加权平均值”]=df[“数据乘以权重”].sum/df[“权重”[u其中不为空].sum
df=df.dropcolumns=[''数据乘以权重',''权重,其中不为空']
返回df
调用函数
dfg=df.groupby[‘经销商’,‘阈值’]。加权平均值,‘价格’,‘收到数量’
显示头
日期经销商阈值数量收到价格运费经销商交货成本新鲜度天数蛋白质类型总计距离目的地加权平均值
0 2017-12-22金州食品50 39037 0.5 0.07 0.6 3.39鸡肉901.0美国0.839475
1 2017-12-27金州食品85 35432 1.8 0.07 1.9 3.39牛肉901.0美国1.950728
2 2017-12-29金州食品50 32142 0.50.07 0.6 3.39鸡肉901.0美国0.839475
3 2017-12-30金州食品85 34516 1.8 0.07 1.9 3.39牛肉901.0美国1.950728
4 2018-01-02金州食品85 39930 1.8 0.07 1.9 3.39牛肉901.0美国1.950728
5:塑造数据框和绘图
作为pd进口熊猫
将matplotlib.pyplot作为plt导入
将matplotlib.dates导入为mdates
导入seaborn作为sns
从datetime导入timedelta,datetime
将阈值设置为类别
dfg.threshold=dfg.threshold.astype'category'
设置索引
dfg=dfg.set_索引['日期','经销商','蛋白质类型','阈值']
将数据帧形成长格式
dfl=dfg[['weighted_average','price']].stack.reset_index.renamecolumns={'level_4':'cats',0:'values'}
与所有经销商密谋
markers={price:s,加权平均值:X}
对于dfl.protein_type.unique中的pt:
对于dfl.threshold.unique中的t:
数据=dfl[dfl.protein_type==pt&dfl.threshold==t]
如果不是data.empty:用于某些阈值
没有数据
utc=lendata.threshold.unique
f、 axes=plt.subplotsnrows=utc,ncols=1,figsize=20,7,squence=False
对于UTC范围内的j:
p=sns.scatterplot'date','values',data=data,hue='dealer',markers=markers,style='cats',ax=axes[j,0]
p、 设置_titlef'阈值:{t}\n{pt}'
p、 设置_xlimdata.date.min-timedeltadays=60,data.date.max+timedeltadays=60
plt.Legendbox_to_anchor=1.04,0.5,loc=左中,borderaxespad=0
节目
与所有经销商的前两个地块
与单独的经销商密谋
在每组中,加权平均值为一个值。与其将其作为cats的一部分进行打印,不如使用
ud=dfl.DELER.unique
日期\最小值=dfl.date.min
日期=dfl.date.max
对于dfl.protein_type.unique中的pt:
对于dfl.threshold.unique中的t:
数据=dfl[dfl.protein_type==pt&dfl.threshold==t]
if not data.empty:对于某些阈值,没有数据
utc=lendata.threshold.unique
f、 axes=plt.subplotsnrows=utc,ncols=lenud,figsize=30,5,squence=False
对于UTC范围内的j:
就我而言,在列举中:
数据\u d=data[data.dealer==d]。排序\u值['cats','date']。重置\u indexdrop=True
价格=数据[data\u d.cats=='price']
w_avg=data_d[data_d.cats=='加权平均']
p=sns.scatterplot'date','values',data=price,hue='cats',ax=axs[j,i]
如果数据不为空:对于某些阈值,此循环中没有经销商d的数据
p、 hlinesw_avg['values'].unique.tolist、w_avg.date.min、w_avg.date.max、'orange',label='weighted avg'
p、 set_titlef'{d}\n保留:{t}\n{pt}'
p、 设置\u xlimdate\u min-timedeltadays=60,date\u max+timedeltadays=60
p、 legend.set_visibleFalse
labels=[datetime.fromordinalintv.strftime'%Y-%m-%d',用于p.getxticks中的v]
p、 设置xticklabelslabel,旋转=90
其他:
p、 set_titlef'{d}:无可用数据\n保留:{t}\n{pt}'
plt.Legendbox_至_锚=1.04,0.5,loc=左中,borderaxespad=0
节目
前几排
一列图
遍历蛋白质类型、阈值和值的每个唯一组合
up=dfl.protein_type.unique
ud=dfl.DELER.unique
ut=dfl.threshold.unique
日期\最小值=dfl.date.min
日期=dfl.date.max
年份\u fmt=mdate.DateFormatter“%Y-%m-%d”
对于pt in up:
对于ut中的th:
对于ud中的dl:
数据=dfl[dfl.protein_type==pt&dfl.threshold==th&dfl.dealer==dl]
if not data.empty:对于某些阈值,没有数据
价格=数据[data.cats=='price']
w_avg=数据[data.cats=='加权平均']
图,ax=plt.子图尺寸=8,5
p=sns.scatterplot'date','values',data=price,hue='cats',ax=ax
p、 hlinesw_avg['values'].unique.tolist、w_avg.date.min、w_avg.date.max、'orange',label='weighted avg'
p、 set_titlef'{dl}\n保留:{th}\n{pt}'
p、 设置\u xlimdate\u min-timedeltadays=60,date\u max+timedeltadays=120
p、 设置\u xticklabelsp.get\u xticks,旋转=90
p、 xaxis.set_major_formatteryears_fmt
plt.legendbox\u to\u anchor=1.04,0.5,loc='中间偏左',borderaxespad=0
节目
太棒了,非常感谢!希望您喜欢骑马:。@Trenton McKinney这对处理时间序列数据非常有帮助,干得好!太棒了,非常感谢!希望您喜欢骑马:。@Trenton McKinney这对处理时间序列数据非常有帮助,干得好!