pandas表格渲染调用render()报错TypeError:第一个参数必须可调用
问题解析与解决
问题描述
同一程序中,第一段代码可正常生成用于HTML邮件的pandas样式表格,但对筛选后的DataFrame应用相同逻辑生成第二个表格时,调用render()方法抛出错误:
TypeError: the first argument must be callable
可正常运行的第一段代码
import numpy as np import pandas as pd import locale money = [10000000, 2200000000, 10241100000.4521, 20224400000.75895] honey = [30.6427984591421, 9584.28792256921, 37008.6603, 211200.2304295] ltrs = ["a", "b", "a", "c"] YRMO = ["202211", "202210", "202211", "202210"] org = ['Main','Main', 'Jr', 'Jr'] df = pd.DataFrame( zip(money, honey, ltrs, YRMO, org), columns=["money", "honey", "ltrs", "YRMO", "org"] ) YRMOs = sorted(set(df["YRMO"])) pivot = df.pivot_table( values=["money", "honey"], index="ltrs", columns=["YRMO"], aggfunc={"money": np.sum, "honey": np.sum}, margins=True, margins_name="Total", ) pivot = pivot.drop("Total", axis=1, level=1) pivot = pivot.fillna(0) pivot["Var 1"] = pivot["money"][max(YRMOs)] - pivot["money"][min(YRMOs)] pivot["Var 2"] = pivot["honey"][max(YRMOs)] - pivot["honey"][min(YRMOs)] def color(val): global color if val[0] == '$' and float(val[1:].replace(",", "")) >1000: color = 'red' else: color = 'green' return f'color: {color}' locale.setlocale(locale.LC_ALL, "us_US.UTF-8") pivot = pivot.applymap(lambda x: locale.currency(val=x, grouping=True, symbol=True)).apply(lambda x: x.str.replace(pat=r"\.\d{2}",repl="", regex=True)) pivot = pivot.style.applymap(color, subset=['Var 1', 'Var 2']) html_pivot = pivot.render()
运行报错的第二段代码
pivot2 = df[df['org'] == 'Jr'].pivot_table( values=["money", "honey"], index="ltrs", columns=['YRMO'], aggfunc={"money": np.sum, "honey": np.sum}, margins = True, margins_name = 'Total' ) pivot2 = pivot2.drop("Total", axis=1, level=1) pivot2 = pivot2.fillna(0) pivot2["Var 1"] = pivot2["money"][max(YRMOs)] - pivot2["money"][min(YRMOs)] pivot2["Var 2"] = pivot2["honey"][max(YRMOs)] - pivot2["honey"][min(YRMOs)] pivot2 = pivot2.applymap(lambda x: locale.currency(val=x, grouping=True, symbol=True)).apply(lambda x: x.str.replace(pat=r"\.\d{2}",repl="", regex=True)) pivot2 = pivot2.style.applymap(color, subset=['Var 1', 'Var 2']) html_pivot = pivot2.render()
问题原因
核心bug在color函数内的global color声明:
- 第一次调用
pivot.style.applymap(color)时,这个全局声明会将原本是函数类型的color覆盖成字符串类型('red'或'green')。 - 第二次调用
applymap(color)时,color已经是字符串,不再是可调用的函数,因此触发TypeError。
解决办法
删除color函数中的global color声明,改用局部变量存储颜色值,避免覆盖函数本身:
def color(val): # 移除global声明,使用局部变量 if val[0] == '$' and float(val[1:].replace(",", "")) > 1000: color_val = 'red' else: color_val = 'green' return f'color: {color_val}'
修正后的完整代码
import numpy as np import pandas as pd import locale money = [10000000, 2200000000, 10241100000.4521, 20224400000.75895] honey = [30.6427984591421, 9584.28792256921, 37008.6603, 211200.2304295] ltrs = ["a", "b", "a", "c"] YRMO = ["202211", "202210", "202211", "202210"] org = ['Main','Main', 'Jr', 'Jr'] df = pd.DataFrame( zip(money, honey, ltrs, YRMO, org), columns=["money", "honey", "ltrs", "YRMO", "org"] ) YRMOs = sorted(set(df["YRMO"])) # 第一段表格逻辑 pivot = df.pivot_table( values=["money", "honey"], index="ltrs", columns=["YRMO"], aggfunc={"money": np.sum, "honey": np.sum}, margins=True, margins_name="Total", ) pivot = pivot.drop("Total", axis=1, level=1) pivot = pivot.fillna(0) pivot["Var 1"] = pivot["money"][max(YRMOs)] - pivot["money"][min(YRMOs)] pivot["Var 2"] = pivot["honey"][max(YRMOs)] - pivot["honey"][min(YRMOs)] # 修正后的color函数 def color(val): if val[0] == '$' and float(val[1:].replace(",", "")) > 1000: color_val = 'red' else: color_val = 'green' return f'color: {color_val}' locale.setlocale(locale.LC_ALL, "us_US.UTF-8") pivot = pivot.applymap(lambda x: locale.currency(val=x, grouping=True, symbol=True)).apply(lambda x: x.str.replace(pat=r"\.\d{2}",repl="", regex=True)) pivot = pivot.style.applymap(color, subset=['Var 1', 'Var 2']) html_pivot = pivot.render() # 第二段表格逻辑(现在可正常运行) pivot2 = df[df['org'] == 'Jr'].pivot_table( values=["money", "honey"], index="ltrs", columns=['YRMO'], aggfunc={"money": np.sum, "honey": np.sum}, margins = True, margins_name = 'Total' ) pivot2 = pivot2.drop("Total", axis=1, level=1) pivot2 = pivot2.fillna(0) pivot2["Var 1"] = pivot2["money"][max(YRMOs)] - pivot2["money"][min(YRMOs)] pivot2["Var 2"] = pivot2["honey"][max(YRMOs)] - pivot2["honey"][min(YRMOs)] pivot2 = pivot2.applymap(lambda x: locale.currency(val=x, grouping=True, symbol=True)).apply(lambda x: x.str.replace(pat=r"\.\d{2}",repl="", regex=True)) pivot2 = pivot2.style.applymap(color, subset=['Var 1', 'Var 2']) html_pivot2 = pivot2.render()
内容的提问来源于stack exchange,提问作者tonytone
相关产品推荐
相关产品推荐

