【发布时间】:2019-06-11 15:25:43
【问题描述】:
我将所有定义的函数组合成一个class,并使用if、elif进行操作。
我将在下面解释。
首先,我有 3 种类型的情节,combo、line 和 bar。
我知道如何为这三个情节分别定义函数。
其次,我想使用 if 将这 3 个图组合在一个包中。
我试过的代码是:
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
class AP(object):
def __init__(self, dt, date, group, value, value2, value3, value4, value5, value6, TYPE):
self.dt = dt
self.date = date
self.group= carrier
self.value = value
self.col1 = col1
self.col2 = col2
self.col3 = col3
self.col4 = col4
self.TYPE = TYPE
if self.TYPE == "combo":
def ComboChart(self, dt, date, group, value, TYPE):
dataset = pd.read_csv(dt)
dataset['date'] = pd.to_datetime(dataset[date])
dataset['yq'] = pd.PeriodIndex(dataset['date'], freq='Q')
dataset['qtr'] = dataset['date'].dt.quarter
dataset = dataset.groupby([carrier, 'yq', 'qtr'])[value].sum().reset_index()
dataset['total.YQGR'] = dataset[value] / dataset.groupby(['qtr', carrier])[value].transform('shift') - 1
dataset = dataset[np.isfinite(dataset['total.YQGR'])]
dataset['total.R'] = dataset[value] / dataset.groupby(group)[value].transform('first')
dataset.yq = dataset.yq.astype(str)
fig, ax1 = plt.subplots(figsize=(12,7))
ax2=ax1.twinx()
sns.lineplot(x='yq',y='total.R', data=dataset, hue=group, ax=ax1, legend = None, palette = ('navy', 'r'), linewidth=5)
ax1.set_xticklabels(ax1.get_xticks(), rotation=45, fontsize=15, weight = 'heavy')
ax1.set_xlabel("", fontsize=15)
ax1.set_ylabel("")
ax1.set_ylim((0, max(dataset['total.R']) + 0.05))
sns.barplot(x='yq', y='total.YQGR', data=dataset, hue=group, ax=ax2, palette = ('navy', 'r'))
ax2.set_yticklabels(['{:.1f}%'.format(a*100) for a in ax2.get_yticks()])
ax2.set_ylabel("")
ax2.set_ylim((min(dataset['total.YQGR']) - 0.01, max(dataset['total.YQGR']) + 0.2))
ax2.get_legend().remove()
ax2.legend(bbox_to_anchor=(-0.35, 0.5), loc=2, borderaxespad=0., fontsize = 'xx-large')
for groups in ax2.containers:
for bar in groups:
if bar.get_height() >= 0:
ax2.text(
bar.get_xy()[0] + bar.get_width()/1.5,
bar.get_height() + 0.003,
'{:.1f}%'.format(round(100*bar.get_height(),2)),
color='black',
horizontalalignment='center',
fontsize = 12, weight = 'heavy'
)
else:
ax2.text(
bar.get_xy()[0] + bar.get_width()/1.5,
bar.get_height() - 0.008,
'{:.1f}%'.format(round(100*bar.get_height(),2)),
color='black',
horizontalalignment='center',
fontsize = 12, weight = 'heavy'
)
ax1.yaxis.set_visible(False)
ax2.yaxis.set_visible(False)
ax2.xaxis.set_visible(False)
ax1.spines["right"].set_visible(False)
ax1.spines["left"].set_visible(False)
ax1.spines["top"].set_visible(False)
ax1.spines["bottom"].set_visible(False)
ax2.spines["right"].set_visible(False)
ax2.spines["left"].set_visible(False)
ax2.spines["top"].set_visible(False)
ax2.spines["bottom"].set_visible(False)
ax1.set_title(TYPE, fontsize=20)
plt.show()
fig.savefig(TYPE, bbox_inches='tight', dpi=600)
elif self.TYPE == "line":
def line(self, dt, date, carrier, value, value2, TYPE):
dataset = pd.read_csv(dt)
dataset['date'] = pd.to_datetime(dataset[date])
dataset['yq'] = pd.PeriodIndex(dataset['date'], freq='Q')
dataset = dataset.groupby([group, 'yq'])[value, value2].sum().reset_index()
dataset['Arate'] = dataset[value2] / dataset[value]
dataset.yq = dataset.yq.astype(str)
fig, ax1 = plt.subplots(figsize=(12,7))
sns.lineplot(x='yq', y='Arate', data=dataset, hue=group, ax=ax1, linewidth=5)
ax1.set_xticklabels(dataset['yq'], rotation=45, fontsize = 15)
ax1.set_xlabel("")
ax1.set_ylabel("")
ax1.set_ylim((min(dataset['Arate']) - 0.05, max(dataset['Arate']) + 0.05))
ax1.set_yticklabels(['{:.1f}%'.format(a*100) for a in ax1.get_yticks()], fontsize = 18, weight = 'heavy')
ax1.legend(bbox_to_anchor=(0., 1.02, 1., .102), loc=2, borderaxespad=0., ncol = 6)
ax1.yaxis.grid(True)
ax1.spines["right"].set_visible(False)
ax1.spines["left"].set_visible(False)
ax1.spines["top"].set_visible(False)
ax1.spines["bottom"].set_visible(False)
ax1.set_title(TYPE, fontsize = 20)
plt.show()
fig.savefig(TYPE, bbox_inches='tight', dpi=600)
elif self.TYPE == "bar":
def Bar(self, dt, date, group, value3, value4, value5, value6, TYPE):
dataset = pd.read_csv(dt, sep = '|')
dataset['date'] = pd.to_datetime(dataset[date])
dataset['yq'] = pd.PeriodIndex(dataset['date'], freq='Q')
dataset = dataset.groupby([group, 'yq'])[value3, value4, value5, value6].sum().reset_index()
dataset = dataset.groupby([group]).tail(4)
dataset.yq = dataset.yq.astype(str)
dataset = pd.melt(dataset, id_vars = [group, 'yq'], value_vars = [value3, value4, value5, value6])
dataset = dataset.groupby(['variable', group]).value.sum().reset_index()
dataset['L4Qtr'] = dataset.value / dataset.groupby([group]).value.transform('sum')
fig, ax1 = plt.subplots(figsize=(12,7))
sns.barplot(x='variable', y='L4Qtr', data=dataset, hue=group, ax=ax1)
ax1.set_xticklabels(ax1.get_xticklabels(), fontsize=17.5, weight = 'heavy')
ax1.set_xlabel("", fontsize=15)
ax1.set_ylabel("")
ax1.yaxis.set_ticks(np.arange(0, max(dataset['L4Qtr']) + 0.1, 0.05), False)
ax1.set_yticklabels(['{:.1f}%'.format(a*100) for a in ax1.get_yticks()], fontsize = 18, weight = 'heavy')
ax1.legend(bbox_to_anchor=(0., 1.02, 1., .102), loc=2, borderaxespad=0., ncol = 6)
for groups in ax1.containers:
for bar in groups:
ax1.text(
bar.get_xy()[0] + bar.get_width()/2,
bar.get_height() + 0.005,
'{:.1f}%'.format(round(100*bar.get_height(),2)),
color=bar.get_facecolor(),
horizontalalignment='center',
fontsize = 16, weight = 'heavy'
)
ax1.spines["right"].set_visible(False)
ax1.spines["left"].set_visible(False)
ax1.spines["top"].set_visible(False)
ax1.spines["bottom"].set_visible(False)
ax1.set_title(TYPE, fontsize=20)
plt.show()
fig.savefig(TYPE, bbox_inches='tight', dpi=600)
第三,我希望其他人可以简单地使用这个模块,如下所示:
import sys
sys.path.append(r'\\users\desktop\module')
from AP import AP as ap
最后,当有人分配TYPE时,它会自动绘制并保存它。
# This will plot combo chart
ap(r'\\users\desktop\dataset.csv', date = 'DATEVALUE', group = 'GRPS', value = 'total', TYPE = 'combo')
以上是理想的想法。我不需要在其中传递value2 ~ value6,因为combo 不使用它们。
当我想要bar:
# This will plot bar chart
ap(r'\\users\desktop\dataset.csv', date = 'DATEVALUE', group = 'GRPS', value3 = 'col1', value4 = 'col2', value5 = 'col3', value6 = 'col4', TYPE = 'combo')
我的代码不正确,因为发生了错误。看来我需要在其中传递所有参数。
但是,即使我在其中传递了所有参数。没有错误但没有输出。
有什么建议吗?
【问题讨论】:
-
这段代码是否与您正在运行的代码完全相同,包括缩进?一方面,
dataset['Arate]缺少一个结束引号。另一方面,您的if self.TYPE == "combo":行不应具有与def __init__行相同的缩进级别。应该在__init__中的所有内容都应该比def __init__行至少多一级缩进。但是即使你解决了这些问题,你也不能在其他类实例方法中定义类实例方法,所以 ComboChart 和 bar 和 line 将不能作为你对象的方法来访问。 -
嗨,你能解释一下,为什么你不只为这些类型创建子类?这不是更直接吗?
-
@Kevin 我编辑了上面的缩进。实际上购买我正在运行的代码格式正确。此外,您的意思是我不能通过
ComboChart、line和bar在class AP()中定义的函数? -
@jottbe 你的意思是创建 3 个类,
ComboChart、line和bar?这是一个选项,但如果我想创建一个“全局”函数(意味着有人只需要我们ap())并且他/她可以分配什么类型,我认为这很方便。 -
@PeterChen:是的,这将是我建议的标准解决方案,如果您出于某种原因想隐藏类结构,只需创建一个包含实际实现的实例并且什么都不做的第四个否则将方法调用转发给实现类(那时可能几乎没有自己的代码)。请参阅下面的答案(评论太小,无法在 ocmment 中写下更多详细信息)。
标签: python function if-statement package user-defined-functions