【问题标题】:Apply function for multiple dataframes and columns对多个数据框和列应用函数
【发布时间】:2019-10-10 13:30:27
【问题描述】:

您好,我正在使用两个数据框,需要应用自定义函数,但出现以下错误:ValueError: ('The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().', 'occurred at index 0')。我知道为什么会发生这种情况,但不知道如何解决问题。

第一个数据框包含当年所有可工作天数的列表:

print(df_workable)
          Date  workable_day  inv_workable_day  day  month
1   2019-01-02           1.0              22.0    2      1
2   2019-01-03           2.0              21.0    3      1
3   2019-01-04           3.0              20.0    4      1
6   2019-01-07           4.0              19.0    7      1
7   2019-01-08           5.0              18.0    8      1
..         ...           ...               ...  ...    ...
364 2019-12-31          20.0               1.0   31     12

第二个数据框包含有关某些日期值和标志的数据。

print(df)
       day_a1     wday_a1     iwday_a1       flag
0        24.0         4.0          6.0        2.1
1         NaN         NaN          NaN        NaN
3        31.0        22.0          1.0        2.2
4        27.0        18.0          5.0  3.3.2.1.3
26816    25.0        19.0          5.0          1
26817    31.0         NaN          NaN        3.2

我正在尝试应用一个函数,该函数将根据多个条件从任一数据帧返回日期(但为了简单起见,我只是使用“this”和“that”)。这是函数:

def rec_date(row):
    if row['flag'] == '2.1':
        if df_workable[df_workable['workable_day'] == int(row['wday_a1']) & df_workable['month'] == 1]['day'] <= dt.datetime.today().day:
            val = "this"
        else:
            val = "that"
    else:
        val = "Still missing"
    return val

问题是当我试图解决条件2.1 时,我需要遍历df 的每一行并检查条件。问题出现了,因为当它试图迭代每一行时,它不知道要迭代 df_workable 上的哪一行,所以它需要一个额外的参数 (.all(),.any (),ETC...)。但是我不想迭代,而只是提取对应的值:

df_workable[df_workable['workable_day'] == 4 & df_workable['month'] == 1]['day']

(我正在传递4 硬编码,因为它将是从 df['wday_a1'] 传递的第一个值)。并且输出应该是7。与 dt.datetime.today().day 相比,该值是 10,将返回 true。我已经分别测试了这两个函数,它们确实返回了预期的输出。但是,由于(我相信)上述原因,当applying 这些函数在数据帧上运行时,就会出现问题。 通过函数后,我希望有这个:

df['rec_date'] = df.apply(rec_date,axis=1)
           day_a1     wday_a1     iwday_a1       flag         rec_date
    0        24.0         4.0          6.0        2.1             this
    1         NaN         NaN          NaN        NaN    Still missing
    3        31.0        22.0          1.0        2.2    Still missing
    4        27.0        18.0          5.0  3.3.2.1.3    Still missing
    26816    25.0        19.0          5.0          1    Still missing
    26817    31.0         NaN          NaN        3.2    Still missing

【问题讨论】:

    标签: python pandas dataframe apply


    【解决方案1】:

    您的代码有两个小问题:

    1. 您想将两个条件与&amp; 组合在一起,但您应该将这些条件中的每一个都括在括号中以清楚地分隔它们:(x==...) &amp; (y=...)
    2. 此检查的结果具有系列的形式(其中只有一个观察值)。 Python 不确定如何将这一系列布尔值转换为一个布尔值,因为如果该系列有多个值,它不知道如何聚合它们(如果所有值都是 True 或者是否足够,则 Series 是否应该只产生一个 True如果其中至少有一个是 True,...)。因此,您应该通过在支票中添加 series.all()series.any() 来澄清这一点。
    def rec_date(row):
        if row['flag'] == '2.1':
            if (df_workable[(df_workable['workable_day'] == int(row['wday_a1'])) & (df_workable['month'] == 1)]['day'] <= dt.datetime.today().day).all():
                val = "this"
            else:
                val = "that"
        else:
            val = "Still missing"
        return val
    

    输出:

           day_a1  wday_a1  iwday_a1       flag       rec_date
    0        24.0      4.0       6.0        2.1           this
    1         NaN      NaN       NaN        NaN  Still missing
    3        31.0     22.0       1.0        2.2  Still missing
    4        27.0     18.0       5.0  3.3.2.1.3  Still missing
    26816    25.0     19.0       5.0          1  Still missing
    26817    31.0      NaN       NaN        3.2  Still missing
    

    【讨论】:

    • 好的,我明白你在说什么。第一部分,与单个值(即今天)相比,返回具有单个值的系列(因为每年只有一天/一个月的组合)确实引发了问题。此外,据我了解并考虑到这种特殊情况(该系列只有 1 个值),使用 .any().all() 会产生相同的效果吗?谢谢你的回答。
    • 您的陈述部分正确。不是将 Series 与引发问题的单个值进行比较。那部分会起作用,它只会返回一系列布尔值。问题是当你运行if Series: 时它会失败,因为你的 if 语句需要一个布尔值。默认情况下,即使长度为 1,pd.Series 的布尔值也不会转换为单个布尔值,因此您必须明确告诉 Python 如何断言该系列是否“为”真。很高兴我能帮上忙 :) 祝你好运!
    【解决方案2】:

    所以,让我们把这个陈述分解一下:

    df_workable[df_workable['workable_day'] == 4 &amp; df_workable['month'] == 1]['day']

    1. df_workable:完整的DataFrame
    2. df_workable[df_workable['workable_day'] == int(row['wday_a1']) &amp; df_workable['month'] == 1]:您正在根据 workable_daymonth 的特定值过滤 DataFrame。这将返回一个新的 DataFrame,其中包含 整个 DataFrame 的过滤结果。
    3. df_workable[df_workable['workable_day'] == int(row['wday_a1']) &amp; df_workable['month'] == 1]['day']:这将获取在步骤 2 中返回的 DataFrame 并访问其 ['day'] 列。这将返回一个 pandas.Series 对象,其中包含 DataFrame 的 daycolumn 的所有值。

    这意味着,当您执行df_workable[df_workable['workable_day'] == int(row['wday_a1']) &amp; df_workable['month'] == 1]['day'] &lt;= dt.datetime.today().day 时,您正在尝试将整个系列对象(其中包含与每一行对应的多个值)与单个日期时间值进行比较,NOT 遍历行.

    我并没有真正得到你想要做的比较,但按照你目前的逻辑似乎不可能完成。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-20
      • 2021-07-11
      • 2021-02-26
      • 1970-01-01
      相关资源
      最近更新 更多