如何在 Pandas 中创建 groupby 子图?
How to create groupby subplots in Pandas?
我有一个数据框,其中包含犯罪的时间序列数据,其中有一个方面是进攻(看起来像下面的格式)。我想在数据框上执行 groupby 图,以便可以探索随时间推移的犯罪趋势。
Offence Rolling year total number of offences Month
0 Criminal damage and arson 1001 2003-03-31
1 Drug offences 66 2003-03-31
2 All other theft offences 617 2003-03-31
3 Bicycle theft 92 2003-03-31
4 Domestic burglary 282 2003-03-31
我有一些代码可以完成这项工作,但它有点笨拙,而且它失去了 Pandas 在单个图上提供的时间序列格式。 (我附上了一张图片来说明)。任何人都可以为我可以使用的此类情节推荐一个成语吗?
我想求助于 Seaborn,但我不知道如何将 xlabel 格式化为时间序列。
subs = []
for idx, (i, g) in enumerate(df.groupby("Offence")):
subs.append({"data": g.set_index("Month").resample("QS-APR", how="sum").ix["2010":],
"title":i})
ax = plt.figure(figsize=(25,15))
for i,g in enumerate(subs):
plt.subplot(5, 5, i)
plt.plot(g['data'])
plt.title(g['title'])
plt.xlabel("Time")
plt.ylabel("No. of crimes")
plt.tight_layout()
这是 Pandas 中 6 个散点图的可重现示例,连续 6 年从 pd.groupby()
获得。 x 轴是当年的油价(布伦特),y 轴是同年的 sp500 值。
import matplotlib.pyplot as plt
import pandas as pd
import Quandl as ql
%matplotlib inline
brent = ql.get('FRED/DCOILBRENTEU')
sp500 = ql.get('YAHOO/INDEX_GSPC')
values = pd.DataFrame({'brent':brent.VALUE, 'sp500':sp500.Close}).dropna()["2009":"2015"]
fig, axes = plt.subplots(2,3, figsize=(15,5))
for (year, group), ax in zip(values.groupby(values.index.year), axes.flatten()):
group.plot(x='brent', y='sp500', kind='scatter', ax=ax, title=year)
这会产生下面的图:
(以防万一,从这些图中您可以推断出 2010 年石油和 sp500 之间存在很强的相关性,但在其他年份则不然)。
您可以在 group.plot()
中更改 kind
以使其适合您的特定种类或数据。我预计,pandas 将保留 x 轴的日期格式(如果您的数据中有)。
Altair 在这种情况下效果很好。
import matplotlib.pyplot as plt
import pandas as pd
import quandl as ql
df = ql.get(["NSE/OIL.1", "WIKI/AAPL.1"], start_date="2013-1-1")
df.columns = ['OIL', 'AAPL']
df['year'] = df.index.year
from altair import *
Viz #1- year/No 列没有颜色
Chart(df).mark_point(size=1).encode(x='AAPL',y='OIL').configure_cell(width=200, height=150)
Viz #2- year/columns 年
没有颜色
Chart(df).mark_point(size=1).encode(x='AAPL',y='OIL', column='year').configure_cell(width=140, height=70).configure_facet_cell(strokeWidth=0)
Viz #3- 按年份填色
Chart(df).mark_point(size=1).encode(x='AAPL',y='OIL', color='year:N').configure_cell(width=140, height=70)
在 pandas 中绘制组的惯用方法实际上是 pivot the groups into columns (不是 groupby):
table = df.pivot_table(index='Month', columns='Offence', values='Total', aggfunc=sum)
# Offence Arson Bicycle Burglary Drug Theft Violent
# Month
# 2020-01-31 525 435 303 363 653 762
# 2020-02-29 180 146 438 177 498 381
# 2020-03-31 375 546 421 485 233 277
# ...
# 2021-12-31 329 344 490 550 592 385
Pandas然后可以自动生成subplots per column in a given layout:
table.plot(subplots=True, layout=(3, 2))
I would turn to seaborn but I can't work out how to format the xlabel as timeseries.
对于 seaborn,保持数据的长格式而不旋转。假设日期已经转换 to_datetime
, format the tick labels using autofmt_xdate
:
g = sns.relplot(kind='line', data=df, x='Month', y='Total',
hue='Offence', col='Offence', estimator=sum,
col_wrap=2, height=2, aspect=2, legend=False)
g.fig.autofmt_xdate()
我有一个数据框,其中包含犯罪的时间序列数据,其中有一个方面是进攻(看起来像下面的格式)。我想在数据框上执行 groupby 图,以便可以探索随时间推移的犯罪趋势。
Offence Rolling year total number of offences Month
0 Criminal damage and arson 1001 2003-03-31
1 Drug offences 66 2003-03-31
2 All other theft offences 617 2003-03-31
3 Bicycle theft 92 2003-03-31
4 Domestic burglary 282 2003-03-31
我有一些代码可以完成这项工作,但它有点笨拙,而且它失去了 Pandas 在单个图上提供的时间序列格式。 (我附上了一张图片来说明)。任何人都可以为我可以使用的此类情节推荐一个成语吗?
我想求助于 Seaborn,但我不知道如何将 xlabel 格式化为时间序列。
subs = []
for idx, (i, g) in enumerate(df.groupby("Offence")):
subs.append({"data": g.set_index("Month").resample("QS-APR", how="sum").ix["2010":],
"title":i})
ax = plt.figure(figsize=(25,15))
for i,g in enumerate(subs):
plt.subplot(5, 5, i)
plt.plot(g['data'])
plt.title(g['title'])
plt.xlabel("Time")
plt.ylabel("No. of crimes")
plt.tight_layout()
这是 Pandas 中 6 个散点图的可重现示例,连续 6 年从 pd.groupby()
获得。 x 轴是当年的油价(布伦特),y 轴是同年的 sp500 值。
import matplotlib.pyplot as plt
import pandas as pd
import Quandl as ql
%matplotlib inline
brent = ql.get('FRED/DCOILBRENTEU')
sp500 = ql.get('YAHOO/INDEX_GSPC')
values = pd.DataFrame({'brent':brent.VALUE, 'sp500':sp500.Close}).dropna()["2009":"2015"]
fig, axes = plt.subplots(2,3, figsize=(15,5))
for (year, group), ax in zip(values.groupby(values.index.year), axes.flatten()):
group.plot(x='brent', y='sp500', kind='scatter', ax=ax, title=year)
这会产生下面的图:
(以防万一,从这些图中您可以推断出 2010 年石油和 sp500 之间存在很强的相关性,但在其他年份则不然)。
您可以在 group.plot()
中更改 kind
以使其适合您的特定种类或数据。我预计,pandas 将保留 x 轴的日期格式(如果您的数据中有)。
Altair 在这种情况下效果很好。
import matplotlib.pyplot as plt
import pandas as pd
import quandl as ql
df = ql.get(["NSE/OIL.1", "WIKI/AAPL.1"], start_date="2013-1-1")
df.columns = ['OIL', 'AAPL']
df['year'] = df.index.year
from altair import *
Viz #1- year/No 列没有颜色
Chart(df).mark_point(size=1).encode(x='AAPL',y='OIL').configure_cell(width=200, height=150)
Viz #2- year/columns 年
没有颜色Chart(df).mark_point(size=1).encode(x='AAPL',y='OIL', column='year').configure_cell(width=140, height=70).configure_facet_cell(strokeWidth=0)
Viz #3- 按年份填色
Chart(df).mark_point(size=1).encode(x='AAPL',y='OIL', color='year:N').configure_cell(width=140, height=70)
在 pandas 中绘制组的惯用方法实际上是 pivot the groups into columns (不是 groupby):
table = df.pivot_table(index='Month', columns='Offence', values='Total', aggfunc=sum)
# Offence Arson Bicycle Burglary Drug Theft Violent
# Month
# 2020-01-31 525 435 303 363 653 762
# 2020-02-29 180 146 438 177 498 381
# 2020-03-31 375 546 421 485 233 277
# ...
# 2021-12-31 329 344 490 550 592 385
Pandas然后可以自动生成subplots per column in a given layout:
table.plot(subplots=True, layout=(3, 2))
I would turn to seaborn but I can't work out how to format the xlabel as timeseries.
对于 seaborn,保持数据的长格式而不旋转。假设日期已经转换 to_datetime
, format the tick labels using autofmt_xdate
:
g = sns.relplot(kind='line', data=df, x='Month', y='Total',
hue='Offence', col='Offence', estimator=sum,
col_wrap=2, height=2, aspect=2, legend=False)
g.fig.autofmt_xdate()