如何使用Pandas中的数据将时间序列线图转换为条形图?

huangapple go评论72阅读模式
英文:

How do I turn a time series line plot into a bar plot using data from Pandas?

问题

问题

我有一个包含3个子图的图表,显示了两个数据集的结果。我想让子图A使用柱状图,而其他两个使用折线图。我已经让所有三个子图都使用了折线图,但是尽管尝试了几天,我无法让子图A显示柱状图。如果我使用Pandas内置的绘图函数df.plot(kind="bar")而不是ax.plot,则可以绘制柱状图,但这会破坏我的子图自定义,并且与图表的其余部分不一致,因此我希望尽可能使用ax.plot

代码(工作示例)

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

data = {}
dlist = ['Data 1', 'Data 2']
data['mean_1'] = [0.5, -0.5, 0.5, -0.5, 0.5]
data['std_1'] = [0.2, -0.2, 0.2, -0.2, 0.2]
data['count_1'] = [50, 200, 50, 200, 50]
data['mean_2'] = [0.4, -0.4, 0.4, -0.4, 0.4]
data['std_2'] = [0.16, -0.16, 0.16, -0.16, 0.16]
data['count_2'] = [70, 160, 40, 240, 40]

df = pd.DataFrame.from_dict(data)
df['time'] = pd.date_range('2000-01-01 00:00:00', '2000-01-02 00:00:00', freq='6H')
df = df.set_index('time')

colors = ['red', 'cornflowerblue']
mean_cols = [col for col in df.columns if 'mean' in col]
std_cols = [col for col in df.columns if 'std' in col]
count_cols = [col for col in df.columns if 'count' in col]

我尝试了两种使用ax.bar的方法,如下所示。
第一种方法与子图B和C相同,只是使用ax.bar代替ax.plot。它会导致错误"TypeError: bar() missing 1 required positional argument: 'height'"。我不知道如何引用数据帧以获取"height"。
第二种方法将时间和y轴值转化为列表,并将它们用作ax.bar的前两个参数。我得到"ValueError: too many values to unpack (expected 1)"的错误。柱状图确实绘制出来,但它们与数据不匹配。

datelist = list(df.index.values)
col_list = df[df.columns[2]].values.tolist()

# 绘图初始化
fig, (ax1, ax2, ax3) = plt.subplots(3, figsize=(8, 11))
start, end = '2000-01-01', '2000-01-02'
fig.suptitle('Jan 1中的数据', fontsize=27, x=0.5)

# 子图1- 计数
i = 0
for f in dlist:
    p, = ax1.plot(df.loc[start:end, count_cols[i]], color=colors[i])
    # p, = ax1.bar(df.loc[start:end, count_cols[i]], color=colors[i]) ## 第一种解决方法 ##
    # p, = ax1.bar(datelist, col_list, color=colors[0]) ## 第二种解决方法 ##
    df[['count_'+str(i+1)]].plot(kind='bar', color=colors[i], alpha=0.5)
    i = i + 1

# 子图2- 均值
i = 0
for f in dlist:
    p, = ax2.plot(df.loc[start:end, mean_cols[i]], color=colors[i])
    i = i + 1

# 子图3- 标准差
i = 0
for f in dlist:
    p, = ax3.plot(df.loc[start:end, std_cols[i]], color=colors[i])
    i = i + 1

# 调整和保存
fig.autofmt_xdate(rotation=0, ha='center')
plt.show()

问题

如何将上图中的线条转化为柱状图,使用ax.bar或其他类似的ax方法?我不想使用Pandas内置的绘图函数。

英文:

The Problem

I have a plot with 3 subplots showing results from two datasets. I want subplot A to use bars and the other two to use lines. I got all three subplots to use lines, but I can't get bars working on subplot A despite fiddling with it for several days. I get bars if I use the Pandas build-in plotting function df.plot(king="bar") instead of ax.plot, but that breaks my subplot customizations and is inconsistent with the rest of the plot, so I want to use ax.plot if possible.

Code (working example)

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

data   = {}
dlist = ['Data 1', 'Data 2']
data['mean_1']=[0.5,-0.5,0.5,-0.5,0.5]
data[ 'std_1']=[0.2,-0.2,0.2,-0.2,0.2]
data['count_1']=[50,200,50,200,50]
data['mean_2']=[0.4,-0.4,0.4,-0.4,0.4]
data[ 'std_2']=[0.16,-0.16,0.16,-0.16,0.16]
data['count_2']=[70,160,40,240,40]

df         = pd.DataFrame.from_dict(data)
df['time'] = pd.date_range('2000-01-01 00:00:00','2000-01-02 00:00:00',freq='6H')
df         = df.set_index('time')
df

colors     = ['red', 'cornflowerblue']
mean_cols  = [col for col in df.columns if 'mean'  in col]
std_cols   = [col for col in df.columns if 'std'   in col]
count_cols = [col for col in df.columns if 'count' in col]

I've tried two methods using ax.bar, highlighted below.
The first is just the same as subplots B and C but using ax.bar instead of ax.plot. It gives me the error "TypeError: bar() missing 1 required positional argument: 'height'". I can't figure how how to reference the dataframe for the "height".
The second turns the time and y-axis values into lists and uses those for the first two arguments in ax.bar. I get "ValueError: too many values to unpack (expected 1)". Bars do plot, but they don't match the data.

datelist = list(df.index.values)
col_list = df[df.columns[2]].values.tolist()

#Plot initialization
fig, (ax1, ax2, ax3) = plt.subplots(3, figsize=(8, 11))
start, end = '2000-01-01', '2000-01-02'
fig.suptitle('Stuff over Jan 1',fontsize=27,x=0.5)

#Subplot 1- Counts
i     = 0
for f in dlist:
    p,= ax1.plot(df.loc[start:end, count_cols[i]],color=colors[i])
#    p,= ax1.bar(df.loc[start:end, count_cols[i]],color=colors[i]) ##First solution##
#    p,= ax1.bar(datelist,col_list,color=colors[0]) ##Second solution##
    df[['count_'+str(i+1)]].plot(kind='bar',color=colors[i],alpha=0.5)
    i = i+1

#Subplot 2- Means
i = 0
for f in dlist:
    p,= ax2.plot(df.loc[start:end, mean_cols[i]],color=colors[i])
    i=i+1

#Subplot 3- Stan. Dev.
i = 0
for f in dlist:
    p,= ax3.plot(df.loc[start:end,std_cols[i]],color=colors[i])
    i=i+1

#Adjustments and save
fig.autofmt_xdate(rotation=0,ha='center')
plt.show()

如何使用Pandas中的数据将时间序列线图转换为条形图?

The Question

How do I turn the lines in the posted image into bars using ax.bar or another similar ax method? I don't want to use the pandas built-in plotting function.

答案1

得分: 1

  • pandas.DataFrame.plot 使用 matplotlib 作为默认后端。
  • 线性图具有日期时间 xtick 位置,而条形图的 xticks 是从0开始索引的。
英文:
  • pandas.DataFrame.plot uses matplotlib as the default backend.
  • The line plots have datetime xtick locations, while the xticks of bar plot are 0 indexed.
import pandas as pd
import matplotlib.pyplot as plt

# sample data
data =\
{pd.Timestamp('2000-01-01 00:00:00'): {'count_1': 50, 'count_2': 70, 'mean_1': 0.5, 'mean_2': 0.4, 'std_1': 0.2, 'std_2': 0.16},
 pd.Timestamp('2000-01-01 06:00:00'): {'count_1': 200, 'count_2': 160, 'mean_1': -0.5, 'mean_2': -0.4, 'std_1': -0.2, 'std_2': -0.16},
 pd.Timestamp('2000-01-01 12:00:00'): {'count_1': 50, 'count_2': 40, 'mean_1': 0.5, 'mean_2': 0.4, 'std_1': 0.2, 'std_2': 0.16},
 pd.Timestamp('2000-01-01 18:00:00'): {'count_1': 200, 'count_2': 240, 'mean_1': -0.5, 'mean_2': -0.4, 'std_1': -0.2, 'std_2': -0.16},
 pd.Timestamp('2000-01-02 00:00:00'): {'count_1': 50, 'count_2': 40, 'mean_1': 0.5, 'mean_2': 0.4, 'std_1': 0.2, 'std_2': 0.16}}

df = pd.DataFrame.from_dict(data, orient='index')

colors = ['red', 'cornflowerblue']

#Plot initialization
fig, axes = plt.subplots(3, figsize=(8, 11), sharex=False, tight_layout=True)
axes = axes.flat
fig.suptitle('Stuff over Jan 1', fontsize=27, x=0.5)

# add a H:M time column for the bar x-axis
df = df.assign(time=df.index.strftime('%H:%M'))

# plot the dataframe columns directly to the assigned axes
df.plot(kind='bar', x='time', y=['count_1', 'count_2'], color=colors, rot=0, alpha=0.5, ax=axes[0])
df.plot(y=['mean_1', 'mean_2'], color=colors, alpha=0.5, rot=0, ax=axes[1])
df.plot(y=['std_1', 'std_2'], color=colors, alpha=0.5, rot=0, ax=axes[2])

# move the legends
for ax in axes:
    ax.legend(bbox_to_anchor=(1, 0.5), loc='center left', frameon=False)

plt.show()

如何使用Pandas中的数据将时间序列线图转换为条形图?

huangapple
  • 本文由 发表于 2023年6月6日 06:09:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/76410293.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定