【问题标题】:Issue with pd.DataFrame.apply with arguments带有参数的 pd.DataFrame.apply 问题
【发布时间】:2022-08-19 02:54:59
【问题描述】:

我想为原始数据帧的每一行在新数据帧中创建增强数据。

所以,我已经定义了我想在应用中使用的增强方法,如下所示:

def augment(row: pd.Series, column_name: str, target_df: pd.DataFrame, num_samples: int):
    # print(type(row))
    target_df_start_index = target_df.shape[0]
    raw_img = row[column_name].astype(\'uint8\')
    bin_image = convert_image_to_binary_image(raw_img)
    bin_3dimg = tf.expand_dims(input=bin_image, axis=2)
    bin_img_reshaped = tf.image.resize_with_pad(image=bin_3dimg, target_width=128, target_height=128, method=\"bilinear\")

    for i in range(num_samples + 1):
        new_row = row.copy(deep=True)

        if i == 0:
            new_row[column_name] = np.squeeze(bin_img_reshaped, axis=2)
        else:
            aug_image = data_augmentation0(bin_img_reshaped)
            new_row[column_name] = np.squeeze(aug_image, axis=2)

        # display.display(new_row)
        target_df.loc[target_df_start_index + i] = new_row

    # print(target_df.shape)
    # display.display(target_df)

当我这样称呼它时,一切正常:

tmp_df = pd.DataFrame(None, columns=testDF.columns)
augment(testDF.iloc[0], column_name=\'binMap\', target_df=tmp_df, num_samples=4)
augment(testDF.iloc[1], column_name=\'binMap\', target_df=tmp_df, num_samples=4)

但是,当我使用 \'apply\' 方法尝试它时,我得到的打印件或显示工作正常,但生成的数据框显示错误

tmp_df = pd.DataFrame(None, columns=testDF.columns)
testDF.apply(augment, args=(\'binMap\', tmp_df, 4, ), axis=1)

这是应用调用后 o/p 数据的样子 -

,data
<Error>, <Error>
<Error>, <Error>

我究竟做错了什么?

  • 我喜欢你正在检查type(row),这是有道理的。建议你在里面扔一个breakpoint(),然后使用l list / n next 关注.apply() 的进度。 docs.python.org/3/library/functions.html#breakpoint ,参见 pdb 文档。另外,编写一个更简单的 .apply 函数,这样您就可以确信某物按预期工作,然后从那里开始。
  • 我在单个调用的 o/p 上尝试了更简单的应用——应用是为 \'binMap\' 列中的每个单元格计算 SHA1,以验证图像确实不同。对于调试器,我相信我需要将笔记本转换为脚本,然后尝试调试器。

标签: python-3.x pandas dataframe


【解决方案1】:

您的测试非常好,感谢您的清晰说明。 我很高兴成为您的rubber duck

在测试 A 中,你(成功地)弄乱了 testDF.iloc[0][1], 使用某种 Fortran 风格的 API 对于 augment(),在 tmp_df 中留下副作用。

测试 B 是精心构建的 除了.apply() 调用外,保持“相同”。 那么让我们看看,有什么不同? 很难说。 让我们检查一下the docs

啊对! 我们正在使用 .apply() API, 所以我们最好遵循它。 最后它解释说:

返回:Series 或 DataFrame

沿 DataFrame 的给定轴应用 func 的结果。

但是您提供的是return None

现在,我不是来评判的 是否最好有副作用 在目标df 上——这取决于你。 但是 .apply() 会弯曲变形 直到你给它某物好的 存储为自己的结果。 狩猎愉快!

【讨论】:

  • 我修改了返回 target_df 的方法,并在应用调用中将返回值分配给 tmp_df [tmp_df = testDF.apply(augment, args=('binMap', tmp_df, 4, ), axis=1)]。打印 tmp_df 时,我仍然得到相同的错误数据帧。
  • 你有没有其他方法可以重写(不使用循环中的测试 A)来将数据从 src 数据帧复制和扩充到我的目标数据帧?
  • 我的意思是现在源数据框在我尝试打印时会打印完全相同的错误。
  • 修改了return语句以返回行并将apply的o / p重新分配给源数据帧并且它起作用了。我会重新发布解决方案。谢谢你的帮助。
【解决方案2】:

这个改变对我有用——

def augment(row: pd.Series, column_name: str, target_df: pd.DataFrame, num_samples: int):
    # print(type(row))
    target_df_start_index = target_df.shape[0]
    raw_img = row[column_name].astype('uint8')
    bin_image = convert_image_to_binary_image(raw_img)
    bin_3dimg = tf.expand_dims(input=bin_image, axis=2)
    bin_img_reshaped = tf.image.resize_with_pad(image=bin_3dimg, target_width=128, target_height=128, method="bilinear")

    for i in range(num_samples + 1):
        new_row = row.copy(deep=True)

        if i == 0:
            new_row[column_name] = np.squeeze(bin_img_reshaped, axis=2)
        else:
            aug_image = data_augmentation0(bin_img_reshaped)
            new_row[column_name] = np.squeeze(aug_image, axis=2)

        # display.display(new_row)
        target_df.loc[target_df_start_index + i] = new_row

    # print(target_df.shape)
    # display.display(target_df)
    return row

并更新了申请如下:

testDF = testDF.apply(augment, args=('binMap', tmp_df, 4, ), result_type='broadcast', axis=1)

谢谢@J_H。 如果有更好的方法来实现我正在做的事情,请随时提出改进建议。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-06-14
    • 2012-03-22
    • 1970-01-01
    • 1970-01-01
    • 2013-05-26
    • 2019-06-14
    • 2015-06-08
    • 2019-10-25
    相关资源
    最近更新 更多