对多个数据框和列应用功能

时间:2019-10-10 13:30:27

标签: python pandas dataframe apply

您好,我正在处理两个数据框,需要应用自定义函数,但出现以下错误: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()等)。但是,我不想重复,而只是提取与以下内容相对应的值:

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

2 个答案:

答案 0 :(得分:1)

您的代码有两个小问题:

  1. 您想将两个条件与&组合在一起,但是您应该将每个条件用括号括起来以清楚地将它们分开:(x==...) & (y=...)
  2. 此检查的结果具有序列的形式(其中仅包含一个观察值)。 Python不确定如何将这一系列的布尔值转换为一个布尔值,因为万一该系列具有多个值,它将不知道如何进行汇总(如果所有值均为True,则该系列只能得到一个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 :(得分:0)

因此,让我们分解一下这句话:

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

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

这意味着,当您执行df_workable[df_workable['workable_day'] == int(row['wday_a1']) & df_workable['month'] == 1]['day'] <= dt.datetime.today().day时,您正在尝试将整个Series对象(包含与每一行对应的多个值)与单个datetime值进行比较,行。

我没有真正得到您要进行的比较,但是按照您当前的逻辑似乎无法完成。