【发布时间】:2020-11-07 03:32:25
【问题描述】:
有
import pandas as pd
afltv = pd.DataFrame({'FICO': [0, 0, 700, 700],
'LTV': [0, 70, 0, 70],
'Adj': [10, 11, 12, 13]})
gfltv = pd.DataFrame({'FICO': [0, 0, 700, 700],
'LTV': [0, 70, 0, 70],
'Adj': [1, 2, 3, 4]})
df = pd.DataFrame({'Investor': ['a','a','e','f'],
'FICO': [600, 699, 700, 701],
'LTV': [69, 70, 71, 90]})
df2 = pd.DataFrame({'Investor': ['a','a','e','f'],
'FICO': [600, 699, 700, 701],
'LTV': [69, 70, 71, 90]})
dflist = [df,df2]
想要
我想根据以下逻辑将一列Adj 值附加到dflist 中的每个数据帧:
-
Adj值是通过将[FICO, LTV]列中的 max le(最大小于或等于)值与查找数据帧(afltv和gfltv)。 - 有条件地使用查找数据帧:如果输入行的
Investor列是'a',则使用afltv。否则使用gfltv。
期望的输出:
print(df) # the same for df2
Investor FICO LTV value
0 a 600 69 10.0
1 a 699 70 11.0
2 e 700 71 4.0
3 f 701 90 4.0
上一次尝试
我有一个实现需要将近 3 个小时才能完成 400K 行。
-
根据投资者列,设置
table变量。例如,如果df.Investor == 'a'那么table = afltv -
将
df.FICO和df.ltv(df2 相同)分别转换为table.FICO和table.LTV中最接近的值,而无需重复。例如,df.FICO = 699,table.FICO 中的值为 0 和 700,则转换结果应为 0。 -
将步骤 2 的结果存储在变量
cscore和lscore中(对每个变量执行步骤 2 中描述的相同过程) -
将 .loc 与步骤 3 中的变量一起使用以返回标量值 步骤 1 中设置的
table变量
def find_value(row):
###Based on df.Investor (passed as row.Investor), set 'table' to be one
### of the df's established above - those df's contain the desired
### results values in the 'adj' column
if row['Investor'] == 'a':
table = afltv.copy()
else:
table = gfltv.copy()
###Convert FICO (described in step 2) and store in cscore
table.drop(table[table.FICO>row['FICO']].index, inplace=True)
table.reset_index(drop=True, inplace=True)
cscore = table.loc[(table['FICO']-row['FICO']).abs().argsort(), 'FICO'].values[0]
###Convert LTV as described in step 2
table.drop(table[table.LTV>row['LTV']].index, inplace=True)
table.reset_index(drop=True, inplace=True)
lscore = table.loc[(table['LTV']-row['LTV']).abs().argsort(), 'LTV'].values[0]
###Use .loc and the variables we set in order to return a scalar value from
### table.adj
adj = table.loc[(table['LTV']==lscore) & (table['FICO']==cscore), 'Adj'].values
return adj
以这种方式产生所需的输出
for i in dflist:
i['value'] = i.apply(find_value, axis=1).astype(float)
我还有多个以类似方式运行的函数,取一行并返回一个标量值。我尝试将列系列传递给函数以加快速度,但我有返回布尔值的比较,所以这似乎不起作用。
我正在寻求任何改进建议。我有几个关于优化的问题:
-
循环遍历数据框以应用函数是一种不好的做法吗?我应该将它们合并为一个 df 并应用一次吗?
-
在我应用的函数中创建新的 df 并在该函数中运行 .loc 效率低吗?
-
基于问题 2,在函数中转换我用于 .loc(FICO 和 LTV)的值是否更有意义,但跳过 .loc 部分?我可能会在函数之外进行合并,而不是 .loc。
【问题讨论】:
-
您能否提供reproducible way 中的示例数据和预期输出?否则人们将无法测试。
-
好点 - 我将汇总示例数据并更新帖子。谢谢
-
添加示例数据和预期输出,感谢反馈!
-
能否解释一下以明文形式获取
value列的逻辑?例如,定义明确的规则列表或查找值的一系列步骤。没有含糊的词。几乎所有的术语,例如“匹配”、“最接近”、“我想查看的表格”等都没有明确定义。我建议您不要期望潜在的回答者从您冗长的代码中推断出这些逻辑。尝试专注于定义输出的要求,而不是描述(不需要的)代码本身。 -
将问题更新为更清晰,再次感谢您的反馈。您评论的结尾暗示我不希望代码按照当前的方式运行,但它现在确实可以正常工作,我得到了正确的结果 - 我希望得到关于我可以优化的地方的建议我的代码,所以它运行得更快。这就是为什么我解释我正在做的事情背后的逻辑,以防他们是完成相同步骤的更有效方式
标签: python pandas optimization apply