映射列满足特定条件的字典中的值

Posted

技术标签:

【中文标题】映射列满足特定条件的字典中的值【英文标题】:Mapping values from a dictionary where a column meets a particular criteria 【发布时间】:2021-07-23 17:01:18 【问题描述】:

我一直在使用传统的字典映射方法新建一个 Pandas 列,如下所示:

product_costs = x: 1, y: 2, z: 3

df['costs'] = df['product'].map(product_costs)

这一直有效,但最近产品“x”的成本发生了变化 - 例如,从 4 月 1 日起成本从 1 增加到 4。

我的 'df' 也有一个日期列,我试图弄清楚如何将 1 的值映射到 4 月之前的日期列和 4 的值在 4 月之后的日期列。

我可能可以使用 for 循环迭代地执行此操作,即:

df['costs'] = ''

index = 0

for i in df['product']:

    if i == 'x' and df.loc[index, 'date'] < 2021-04-01:

        df.loc[index, 'costs'] = 1
        index += 1

    elif i == 'x' and df.loc[index, 'date'] >= 2021-04-01:

        df.loc[index, 'costs'] = 4
        index += 1

    elif i == 'y':

    etc. etc.

...但是,当我确信可以以更简单的方式实现相同的结果时,这似乎相当冗长乏味。任何人都可以就如何在我的映射中包含“日期”元素提出解决方案吗?

编辑 - 下面的示例数据

date (dd-mm)        product

01-02                  x

01-02                  y

01-02                  z

01-03                  x

01-03                  y

01-03                  z

01-04                  x

01-04                  y

01-04                  z

变成……

date (dd-mm)        product        cost

01-02                  x            1

01-02                  y            2

01-02                  z            3

01-03                  x            1

01-03                  y            2

01-03                  z            3

01-04                  x            4

01-04                  y            2

01-04                  z            3

【问题讨论】:

能否提供样本数据? 当然,请参阅编辑。 【参考方案1】:

np.where()

您可以根据日期条件使用np.where()

首先转换日期to_datetime()。假设您的日期缺少年份 (%d-%m),但您希望年份为 2021:

df['date'] = pd.to_datetime(df['date'], format='%d-%m').apply(lambda x: x.replace(year=2021))

然后以日期为条件使用np.where()进行映射:

costs_pre = 'x': 1, 'y': 2, 'z': 3
costs_post = 'x': 4, 'y': 2, 'z': 3

df['costs'] = np.where(
    df['date'] < '2021-04-01',
    df['product'].map(costs_pre),
    df['product'].map(costs_post))

#         date  product  costs
# 0 2021-02-01        x      1
# 1 2021-02-01        y      2
# 2 2021-02-01        z      3
# 3 2021-03-01        x      1
# 4 2021-03-01        y      2
# 5 2021-03-01        z      3
# 6 2021-04-01        x      4
# 7 2021-04-01        y      2
# 8 2021-04-01        z      3

np.select()

如果你有多个条件,你可以嵌套np.where(),但np.select()会更干净。

例如,如果您的成本在 01-03 发生变化,然后在 01-04 再次发生变化:

costs1 = 'x': 1, 'y': 2, 'z': 3
costs2 = 'x': 4, 'y': 2, 'z': 3
costs3 = 'x': 100, 'y': 2, 'z': 3

conditions = [df['date'] < '2021-03-01', df['date'] < '2021-04-01']
choices = [df['product'].map(costs1), df['product'].map(costs2)]

df['costs'] = np.select(conditions, choices, default=df['product'].map(costs3))

#         date product  costs
# 0 2021-02-01       x      1
# 1 2021-02-01       y      2
# 2 2021-02-01       z      3
# 3 2021-03-01       x      4
# 4 2021-03-01       y      2
# 5 2021-03-01       z      3
# 6 2021-04-01       x    100
# 7 2021-04-01       y      2
# 8 2021-04-01       z      3

【讨论】:

这很好用,感谢您的帮助。最后一个问题,如果产品“x”再次改变成本并且现在有 3 个基于数据关联的可能值 - 我最好的方法是在 np.where 中包含另一个 np.where 吗? @SlowlyLearning 是的,这是一种选择,但另一种选择是np.select()。给我一秒钟更新 @SlowlyLearning 更新为 np.select() 选项【参考方案2】:

熊猫在这里也很有用。 https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.where.html

【讨论】:

以上是关于映射列满足特定条件的字典中的值的主要内容,如果未能解决你的问题,请参考以下文章

如何比较字典值中的多个数组,并将每个数组元素的字典键映射到新数组/列表中

如何将嵌套字典列表与它们的值中的公共键相加? [复制]

在另一列满足条件后计算一列中的值

检查字典中的浮点值以了解 Python 中的条件

熊猫数据框条件 .mean() 取决于特定列中的值

如何在使用 SQL 的重复搜索中排除其他值中的值