gpt4 book ai didi

python - 重构数据帧中列乘法中的错误 'code smell'

转载 作者:行者123 更新时间:2023-12-01 04:50:43 25 4
gpt4 key购买 nike

我还有一个关于效率的问题。我有以下类型的乘法:

df['Allocated'] = df['Base Days'] * df['Base (MW) Allocated'] * 24
df['Bought'] = df['Base Days'] * df['Base (MW) Bought'] * 24
df['Sold'] = df['Base Days'] * df['Base (MW) Bought'] * 24
df['Remaining'] = df['Base Days'] * df['Base (MW) Remaining'] * 24

我正在考虑使用 for 循环 - 但有人在打字方面有更有效的方法吗?或者像这样是最有效的方法。我可以定义一个函数

  def multiply(df['X']): 
return df['X'] * df['Base Days'] * 24

这可能会使代码更可重用。大家还有其他想法吗只是感觉我正在做一个糟糕的代码味道 - 我想要一些关于如何改进它的建议。

最佳答案

这类事情并不存在固有的“糟糕的代码味道”。例如,假设将来其中一列“购买的基础 (MW)”需要与其他列进行不同的处理。在这种情况下,每个不同的乘法步骤都是显式处理的,而不是在函数调用中隐式处理或作为循环的迭代处理,这实际上是一个优点。

但是,我可以理解这样一个事实,即似乎存在浪费的字符,因为您正在重复 *24 的逻辑以及对 'Base Days' 的访问>.

我可能会做的是为将来的扩展创建一些选项或稍后增加灵 active 的方法,但仍然或多或少地使用您的想法:

def baseMultiply(data, colToMul, baseCol='Base Days', convFactor=24, preTreat=None):
col_data = data[colToMult]
if preTreat is not None:
col_data = preTreat(col_data)
return data[baseCol] * col_data * convFactor

然后循环执行乘法和赋值:

col_prefix = "Base (MW) "
for col in ['Allocated', 'Bought', 'Sold', 'Remaining']:
df[col] = baseMultiply(df, col_prefix + col)

然后稍后说您想要删除异常值,但仅限于报告“已购买”数量的情况(这是不现实的,但这只是一个示例)。您可以编写一个辅助函数,例如:

def removeOutlier(lowerBound, upperBound, colData):
return colData.clip(lowerBound, upperBound)

我们可以使用functools.partial将一些参数绑定(bind)到这个家伙。

import functools
boughtColClipper = functools.partial(removeOutlier, 5, 105)

现在我们可以修改上面的循环来检查何时位于 'Bought' 列,并在这种情况下将此函数作为关键字参数 preTreat:

col_prefix = "Base (MW) "
for col in ['Allocated', 'Bought', 'Sold', 'Remaining']:
treatment = None if col != 'Bought' else boughtColClipper
df[col] = baseMultiply(df, col_prefix + col, preTreat=treatment)

现在它至少具有一定的可扩展性,可以允许以后的数据清理、离群值裁剪、缩尾化、变量 z 评分等,这些都是以后出现的常见问题,需要痛苦地返回并破坏早期的代码。

我经常使用的最后一个技巧是名称映射。您可以提供一个字典映射,而不是像我上面所做的那样迭代列名称的列表(这隐含地假设赋值名称将相同或直接从现有名称派生)。

例如,在原来的帖子中,您分配了新名称“Sold”,但在右侧,它是根据“Base (MW) Bought”计算的,不是 “已售基础(兆瓦)”。我认为这是一个拼写错误,因此我在代码中使用了“Base (MW) Sold”。

但我们假设这不是一个拼写错误,并且两个不同的“输出名称”(“买入”和“卖出”)来自一个输入名称(“Base (MW) Bought”)。

namesToAssign = {"Allocated":"Allocated", 
"Bought":"Bought",
"Sold":"Bought",
"Remaining":"Remaining"}

col_prefix = "Base (MW) "
for newCol, oldCol in namesToAssign.iteritems():
treatment = None if newCol != 'Bought' else boughtColClipper
df[newCol] = baseMultiply(df, col_prefix + oldCol, preTreat=treatment)

您甚至可以更进一步,获得从现有列到新输出列以及预处理函数的映射,例如:

namesAndTreatments = {"Allocated":("Allocated", None), 
"Bought":("Bought", boughtColClipper),
"Sold":("Bought", None),
"Remaining":("Remaining", None)}

col_prefix = "Base (MW) "
for newCol, (oldCol, treatment) in namesToAssign.iteritems():
df[newCol] = baseMultiply(df, col_prefix + oldCol, preTreat=treatment)

甚至可以进一步扩展,以便 namesAndTreatments 中的每个值都包含额外的参数、日志处理程序、数据错误时用于后备数据的数据库连接等。一点,您需要将 namesAndTreatments 重构为某种自己的类,并通过解包该类的成员数据属性来使 baseMultiply 等函数起作用(它将有助于划分和测试,而仅仅在其责任中不断增长的 dict 将很难维护)。

关于python - 重构数据帧中列乘法中的错误 'code smell',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28562997/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com