Pandas Dataframe 中本月与前几个月的不同计算

Different calculations for this month compared to previous months in Pandas Dataframe

考虑示例数据:

Month    Members
JUL      10
AUG      10
SEP      10

我想添加一个新列,即 MemberValue,但如果月份不是当前月份(当前为 2021 年 9 月),我希望该列将成员值乘以 10,如果月份值是当前月份,则乘以 100月。预期的输出将是这样的:

Month    Members   MemberValue
JUL      10        100
AUG      10        100
SEP      10        1000

我已经尝试了各种版本的条件语句,并继续我们之前在各种上下文中看到的“真值不明确”。我可以计算月份的三个字母缩写和月份的数值(即 SEP 或 9),但使用它们作为计算 MemberValue 列的比较会产生错误。我确信我遗漏了一些简单的东西,但无法破解这个。感谢您的观看。

我最近一次失败的尝试:

if df.index != months-1:
    df['MemberValue'] = df['Members'] * 10
else:
    df['MemberValue'] = df['Members'] * 100

之前的另一次尝试:

cur_month_name = str(today_date_time.strftime('%b')).upper()
if df['Month'] != cur_month_name:
        df['MemberValue'] = df['Members'] * 10
    else:
        df['MemberValue'] = df['Members'] * 100

也失败了。

您可以使用 strftime 获取缩写月份名称,并使用 np.where 应用您的操作:

cur_month_name = pd.Timestamp.today().strftime('%b').upper()
df['MemberValue'] = np.where(df['Month'] == cur_month_name,
                             df['Members']*100, df['Members']*10)

输出:

>>> df
  Month  Members  MemberValue
0   JUL       10          100
1   AUG       10          100
2   SEP       10         1000

>>> cur_month_name
'SEP'

对于您之前的尝试,您的想法是使用月份名称是好的,但您要求 Python 对值列表(真/假)进行测试。为此,您需要在每一行而不是整个系列上应用测试:

>>> df.apply(lambda x: x['Members']*100 if x['Month'] == cur_month_name
                                        else x['Members']*10, axis=1)

0     100
1     100
2    1000
dtype: int64
curr_month_short = str.upper(pd.Timestamp.now().month_name())[0:3]
df.loc[df['Month'] != curr_month_short, 'MemberValue'] = df['Members'] * 10 
df.loc[df['Month'] == curr_month_short, 'MemberValue'] = df['Members'] * 100 

输出:

Out[13]: 
  Month  Members  MemberValue
0   JUL       10        100.0
1   AUG       10        100.0
2   SEP       10       1000.0

第一行获取月份的简称 - 只需获取今天的月份名称,然后将前 3 个字母切片(并应用 str.upper)即可。

df.loc[df['Month'] != curr_month_short, 'MemberValue'] select df['Month'] 不同于 curr_month_short 的所有行,并将 MemberValue 的值分配给列 MemberValue ].当前月份相同的所有行都相同 curr_month_short

至于你的代码:注意行 df['Month'] != cur_month_name returns a series with boolean values - true or false for each row。 if 语句不知道如何处理它,因此出现错误。 if... else 如果您一次将逻辑应用于一行(比方说,遍历所有行),则逻辑可以很好地工作。

在我的示例中,在 .loc 上使用此条件是您想要它做的:仅获取语句为“真”的行,并将值应用于它们。

您的代码应如下所示:

cur_month_name = str(today_date_time.strftime('%b')).upper()
boolean_series = df['Month'] != cur_month_name
df.loc[boolean_series, 'MemberValue'] = df['Members'] * 10
df.loc[~boolean_series, 'MemberValue'] = df['Members'] * 100

('~'运算符 returns 相反:true 变成 false,false 变成 true)