如何使用分组绘制连续数据
Posted
技术标签:
【中文标题】如何使用分组绘制连续数据【英文标题】:How to plot continous data with grouping 【发布时间】:2021-09-17 01:58:37 【问题描述】:我想要什么
我想为每个 cod
项目绘制图表。例如:1746
、202
...等
但如图所示,我只有一个项目的图表。
我想为每个cod
显示更多图表。
我拥有的数据框
鳕鱼行动日期数量 0 1746 购买 2021-06-15 0:00:00 45 1 202 购买 2021-06-15 0:00:00 60 2 1746 卖出 2021-06-17 0:00:00 1 3 1746 卖出 2021-06-17 0:00:00 3 4 1746 卖出 2021-06-17 0:00:00 7 5 202 卖出 2021-06-17 0:00:00 1 6 202 卖出 2021-06-17 0:00:00 3 7 1746 卖出 2021-06-18 0:00:00 1 8 1746 卖出 2021-06-18 0:00:00 1 9 1746 卖出 2021-06-18 0:00:00 1 10 1746 卖出 2021-06-18 0:00:00 1 11 1746 卖出 2021-06-18 0:00:00 1 12 1746 卖出 2021-06-18 0:00:00 1 13 1746 卖出 2021-06-18 0:00:00 2 14 1746 卖出 2021-06-18 0:00:00 2 15 1746 卖出 2021-06-18 0:00:00 2 16 1746 卖出 2021-06-18 0:00:00 2 17 1746 卖出 2021-06-18 0:00:00 2 18 1746 卖出 2021-06-18 0:00:00 2 19 1746 卖出 2021-06-18 0:00:00 2 20 202 购买 2021-06-19 0:00:00 30 21 202 卖出 2021-06-19 0:00:00 1 22 202 卖出 2021-06-20 0:00:00 3 23 1746 购买 2021-06-21 0:00:00 45 24 1746 卖出 2021-06-22 0:00:00 7上面显示的图表是用下面的代码绘制的。但这只会绘制一个cod
。
# Convert to datetime
df['datetime'] = pd.to_datetime(df['datetime'])
# Negate Sale rows
df.loc[df['action'].eq('Sale'), 'amt'] *= -1
# Calculate the total amount
df['total_amt'] = df['amt'].cumsum()
# Plot datetime vs total_amt
ax = df.plot(x='datetime', y='total_amt', ylabel='Qty', xlabel='Date')
plt.show()
问题
如何分组或使用其他方式为每个 cod
绘制线条?
【问题讨论】:
【参考方案1】:对于matplotlib
和pandas
解决方案,需要进行三项修改。
-
标准
cumsum
将不再起作用,因为每组需要滚动总数。替换为groupby cumsum
。
plot
每个 cod
在一个循环中。
action
列包含单词“sell”而不是“Sale”,因此过滤器应为 df['action'].eq('sell')
。
# Convert to datetime
df['date'] = pd.to_datetime(df['date'])
# Negate sell rows in action column
df.loc[df['action'].eq('sell'), 'qty'] *= -1
# Create a groupby over `cod`
g = df.groupby('cod')
# Calculate the total amount (per group)
df['total_amt'] = g['qty'].cumsum()
fig, ax = plt.subplots()
# Plot for each group in groubpy
for n, g_df in g:
g_df.plot(x='date', y='total_amt',
ylabel='Qty', xlabel='Date',
ax=ax, label=n)
plt.legend(title='cod')
plt.tight_layout()
plt.show()
DataFrame 和导入:
import pandas as pd
from matplotlib import pyplot as plt
df = pd.DataFrame(
'cod': [1746, 202, 1746, 1746, 1746, 202, 202, 1746, 1746, 1746, 1746, 1746,
1746, 1746, 1746, 1746, 1746, 1746, 1746, 1746, 202, 202, 202, 1746,
1746],
'action': ['buy', 'buy', 'sell', 'sell', 'sell', 'sell', 'sell', 'sell',
'sell', 'sell', 'sell', 'sell', 'sell', 'sell', 'sell', 'sell',
'sell', 'sell', 'sell', 'sell', 'buy', 'sell', 'sell', 'buy',
'sell'],
'date': ['2021-06-15 0:00:00', '2021-06-15 0:00:00', '2021-06-17 0:00:00',
'2021-06-17 0:00:00', '2021-06-17 0:00:00', '2021-06-17 0:00:00',
'2021-06-17 0:00:00', '2021-06-18 0:00:00', '2021-06-18 0:00:00',
'2021-06-18 0:00:00', '2021-06-18 0:00:00', '2021-06-18 0:00:00',
'2021-06-18 0:00:00', '2021-06-18 0:00:00', '2021-06-18 0:00:00',
'2021-06-18 0:00:00', '2021-06-18 0:00:00', '2021-06-18 0:00:00',
'2021-06-18 0:00:00', '2021-06-18 0:00:00', '2021-06-19 0:00:00',
'2021-06-19 0:00:00', '2021-06-20 0:00:00', '2021-06-21 0:00:00',
'2021-06-22 0:00:00'],
'qty': [45, 60, 1, 3, 7, 1, 3, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 30, 1,
3, 45, 7]
)
注意cumsum
和groupby cumsum
之间的区别:
df['date'] = pd.to_datetime(df['date'])
df.loc[df['action'].eq('sell'), 'qty'] *= -1
df['cs'] = df['qty'].cumsum() # Standard cumsum
df['gb_cs'] = df.groupby('cod')['qty'].cumsum() # Groupby cumsum
df
:
cod action date qty cs gb_cs
0 1746 buy 2021-06-15 45 45 45
1 202 buy 2021-06-15 60 105 60 # cs has total for both cod
2 1746 sell 2021-06-17 -1 104 44
3 1746 sell 2021-06-17 -3 101 41
4 1746 sell 2021-06-17 -7 94 34
5 202 sell 2021-06-17 -1 93 59 # gb_cs has separate totals per cod
6 202 sell 2021-06-17 -3 90 56
seaborn
的替代方案通过设置 sns.lineplot
的 hue
参数来简化此过程,而不是创建一个 groupby 进行迭代:
import pandas as pd
import seaborn as sns
from matplotlib import pyplot as plt
# DataFrame is the same as above #
# Convert to datetime
df['date'] = pd.to_datetime(df['date'])
# Negate sell rows in action column
df.loc[df['action'].eq('sell'), 'qty'] *= -1
# Calculate the total amount (per group)
df['total_amt'] = df.groupby('cod')['qty'].cumsum()
# Plot using seaborn with hue param set to `cod`
ax = sns.lineplot(
data=df, x='date', y='total_amt',
hue='cod', # Separate lines based on hue column `cod`
ci=None, # Remove Error Shading
palette='pastel', # Set Colour Palette
estimator=None # Plot all observations (like matplotlib)
)
ax.set(xlabel='Date', ylabel='Qty')
ax.xaxis.set_tick_params(rotation=45)
plt.tight_layout()
plt.show()
【讨论】:
您好,Henry,非常感谢您的回答。谢谢你。你能告诉我如何为每个cod
绘制子图吗?我正在寻找一种方法,但还没有找到,你能帮帮我吗?
添加子图fig, axes = plt.subplots(ncols=2)
然后把for循环改成for (n, g_df), ax in zip(g, axes):
【参考方案2】:
根据您发布的信息,我将其重写为:
df['datetime'] = pd.to_datetime(df['datetime'])
# Negate Sale rows
df.loc[df['action'].eq('Sale'), 'amt'] *= -1
# Calculate the total amount
df['total_amt'] = df['amt'].cumsum()
for key, grp in df.groupby(['cod']):
t=ax.plot(grp['datetime'], grp['total_amt'])
plt.legend(t, [f'total amt key'],loc='best')
#ax.set(ylim=[0,100]) <----- if u need to setup y limits
ax.set_ylabel("Qty")
ax.set_xlabel("Date")
【讨论】:
我试过你的代码,但它没有编译...你编译你的代码了吗?检查并尝试更改一些内容以使其正常工作,但无法编译以上是关于如何使用分组绘制连续数据的主要内容,如果未能解决你的问题,请参考以下文章
R语言使用ggplot2包geom_jitter()函数绘制分组(strip plot,一维散点图)带状图(颜色配置:连续色彩离散色彩色彩梯度)实战