【问题标题】:DataFrame as default function argument not working as expectedDataFrame 作为默认函数参数未按预期工作
【发布时间】:2021-04-06 16:26:53
【问题描述】:

我很困惑为什么 DataFrame 作为默认函数参数不能像我预期的那样工作。这让我感到困惑,为什么我仍然必须在函数调用中指定它。

基本上,我创建了一个函数,用于根据键(如左连接)将数据帧合并到主数据帧(我将其设置为默认参数)

简化的数据框(只是同一个学生,不同学科的分数):

dfA = pd.DataFrame ({'student': ['A'],
                     'math_score': [50]})

dfB = pd.DataFrame({'student': ['A'],
                    'eng_score': [70]})

dfC = pd.DataFrame({'student': ['A'],
                    'sci_score': [80]})

函数(我想一一得到他的科目分数,把它们合并到一个主df)

def merge_selected(df_to_merge, main_df = dfA):

    # LEFT JOIN to main_df
    main_df = main_df.merge(right=df_to_merge, how='left', on=['student'])

    return main_df

使用函数合并两次:

dfA = merge_selected(dfB)
dfA = merge_selected(dfC)

现在这是我不明白的。我在第二次合并中丢失了eng_score。不知何故,当我第二次将dfA 分配给merge_selected 时,它被删除了。

  student  math_score  sci_score
0       A          50         80

但是如果我在函数调用中指定了main_df = dfA

dfA = merge_selected(dfB, main_df = dfA)
dfA = merge_selected(dfC, main_df = dfA)

我不输eng_score并得到他所有的分数:

  student  math_score  eng_score  sci_score
0       A          50         70         80

基本上我已经解决了这个问题,但希望有人能对此有所了解。

为什么我仍然必须指定main_df,即使它应该默认为dfA

另外,如果我不指定main_df = dfA,为什么会丢失eng_score

【问题讨论】:

    标签: python python-3.x pandas function dataframe


    【解决方案1】:

    当您使用默认参数 main_df=dfA 定义函数时,函数会“记住”DataFrame dfA 以供将来所有调用使用。让我们给这个 dfA 的“原始形式”起一个名字:orig_dfA。

    现在,给 merge_selected 打第一个电话。您最终使用 orig_dfA 创建了一个新的合并 DataFrame,它存储在内存中的某个位置,与 orig_dfA 不同。

    然后您从函数返回并将 dfA 分配给这个新的合并 DataFrame。事情就是这样。您实际上根本没有更改 orig_dfA。您只需将名称“dfA”指代这个新的合并 DataFrame,它存储在内存中与 orig_dfA 不同的位置。但是该函数仍然附加到 orig_dfA,它没有改变 - 该函数不知道您希望 main_df 的默认值现在成为“dfA”所指的新 DataFrame!

    所以,当涉及到第二个函数调用时,就好像第一个从未发生过一样!

    这里有一个更简单的例子来说明这一点。和以前一样,使用默认值 main_df 定义您的函数。现在,在定义函数之后,立即将 dfA 更改为完全不是 DataFrame 的东西,比如 dfA = 3。现在像​​第一次一样调用你的函数。你会得到完全相同的输出。

    这里发生了两件事:

    1. 在 Python 中,赋值 (=) 运算符只是将名称绑定到内存中的对象/值。语句 x = 3 不能作为“留出一些将由名称“x”引用的内存,并将值 3 放在那里”,这是人们可能直觉所期望的。相反,它更像是“在内存中的某处创建值 3,并让名称“x”引用它”。
    2. 当您设置默认参数时,该默认参数引用的对象/值在函数创建时确定并且是 FIXED。

    在您的情况下,在定义转换为“使 main_df 引用 df_A 当前引用的内存中的对象/值”的函数时设置 main_df=df_A。从这一点开始,您可以让 df_A 引用您喜欢的任何其他内存 - 该函数将始终引用 df_A 在创建函数时引用的同一块内存,而不是 df_A 碰巧引用的任何值函数实际上被调用了。

    【讨论】:

    • 嘿,谢谢你的解释!我只是想澄清一件事。我知道如果我在函数调用期间没有指定 main_df 是什么,它将默认为创建函数时的任何 dfA。但是,如果我确实指定了 main_df = dfA,这是否意味着 main_df 现在将引用 dfA 当前所指的任何内容?
    • 是的,完全正确!不过不要相信我,试试看:)。
    • 嘿,我已经尝试过了。实际上,如果我指定 main_df,它指的是 dfA 当前所指的任何内容。感谢您的详细解释,这很有帮助!
    猜你喜欢
    • 2016-07-01
    • 1970-01-01
    • 2014-05-19
    • 2010-12-30
    • 2014-08-20
    • 2020-03-09
    • 2018-02-01
    • 2022-01-26
    • 2019-10-30
    相关资源
    最近更新 更多