【问题标题】:Create dictionary with two keys where both keys must be met to retrieve value使用两个键创建字典,其中两个键都必须满足才能检索值
【发布时间】:2020-01-22 04:10:04
【问题描述】:

我有两个数据框:

df_one:

person  city   year   col_x
ah       bos   1998
bc       bos   1996
dm       ny    2001
hh       la    1999

df_two:

person   city  range_a  range_b
mk       bos   1995     2004
kk       bos   2004     2017
ab       ny    1977     2019
fc       dc    2001     2005
cc       dc    2006     2019
et       la    1995     2005
tr      mia    1997     2006

我想用基于 df_one 和 df_two 中条件的值填充 df_one、col_x。您将从 df_one 获取城市,从 df_two 匹配城市,并根据 df_one 上的年份在 df_two 范围之间的位置 - 您可以将 df_two 上的人放入 df_one 上的 col_x 中。

示例:df_one 中第一行的“ah” - 城市为 bos,年份为 1998 - 因此该行的 col_x 将是 mk,因为城市匹配且 1998 介于 1995 年和 2004 年之间。

我不太确定从 pandas 开始。我相信它可能是某种具有两个值的嵌套字典,但不确定这是否可能。

【问题讨论】:

  • 我真的不知道在 pandas 上从哪里开始 然后阅读 Pandas 文档。
  • 按照您在 df_one 的最后一行中提到的“la”的条件,1999 年可能落在 df_two 的两个位置 - 因此可以选择“et”和“tr”。请说明您希望如何在多个值之间进行选择。是要取第一个值还是最后一个值?
  • 我认为您需要更清楚地解释您的目标。您在标题中提到您只想在两个键匹配时才检索一个值,然后谈论在键位于其他两个值之间的情况下找到一个值?
  • @instinct246 我将我的 OP 编辑​​得更具体,还修复了数据的拼写错误 - 但是是的,您正在使用“人”列中的数据填充缺失列中的数据
  • @BrettJeffreson 澄清一下 - 当城市匹配并且年份介于范围之间时,您将使用 df_two 的人员列中的值填充 col_x 上的单元格

标签: python dataframe dictionary


【解决方案1】:

这是一种解决方法。 首先,我根据您的描述创建了数据框:

df1 = pd.DataFrame({'A': ['ah','bc','dm','hh'], 'B':['bos','bos','ny','la'], 'C': [1998,1996,2001,1999]})
df2 = pd.DataFrame({'A': ['mk','kk','ab','fc','cc','et','tr'], 'B':['bos','bos','ny','dc','dc','la','la'],'C': [1995,2004,1977,2001,2006,1995,1997], 'D':[2004,2017,2019,2005,2019,2005,2006] })

df1

A   B   C
0   ah  bos 1998
1   bc  bos 1996
2   dm  ny  2001
3   hh  la  1999

df2
A   B   C   D
0   mk  bos 1995    2004
1   kk  bos 2004    2017
2   ab  ny  1977    2019
3   fc  dc  2001    2005
4   cc  dc  2006    2019
5   et  la  1995    2005
6   tr  la  1997    2006

然后将 df1 的行传递给一个函数(检查数据)。该函数将 df1 的每一行与 df2 中的所有行进行比较,并根据您提到的条件从 df2['A'] 返回所有匹配值。 请阅读我对您原始问题的评论。 df1 中的 'la' 将在 df2 中选择 2 个值。 选项 1: 我选择了 df1['D'] 的所有值,并以列表的形式出现。 选项 2:我只选择了所有匹配值中的第一个值,并将其作为奇异值。

您可以选择您想要选择的选项或进一步说明。

选项 1:

def check_data(row):
    return  (df2[ (df2['B'] == row['B']) & (df2['C'] <= row['C']) & (df2['D'] >= row['C'])]['A'].values)
df1['D'] = df1.apply(check_data, axis=1)

df1

A   B   C   D
0   ah  bos 1998    [mk]
1   bc  bos 1996    [mk]
2   dm  ny  2001    [ab]
3   hh  la  1999    [et, tr]

选项 2:

def check_data(row):
    return  (df2[ (df2['B'] == row['B']) & (df2['C'] <= row['C']) & (df2['D'] >= row['C'])]['A'].iloc[0])
df1['D'] = df1.apply(check_data, axis=1)

df1
A   B   C   D
0   ah  bos 1998    mk
1   bc  bos 1996    mk
2   dm  ny  2001    ab
3   hh  la  1999    et

【讨论】:

    【解决方案2】:

    您可以使用 pandas 数据框合并,然后根据您需要的逻辑使用 lambda 表达式来计算列。

    例子:

    import pandas as pd
    

    第一个数据帧:

    df_one = pd.DataFrame([
            {'A': 'ah', 'B': 'bos', 'C': 1998, 'D': ''},
            {'A': 'bc', 'B': 'bos', 'C': 1996, 'D': ''},
            {'A': 'dm', 'B': 'ny', 'C': 2001, 'D': ''},
            {'A': 'hh', 'B': 'la', 'C': 1999, 'D': ''},
        ])
    print("df_one")
    print(df_one)
    

    第二个数据框:

    df_two = pd.DataFrame([
            {'A': 'mk', 'B': 'bos', 'C': 1995, 'D': 2004},
            {'A': 'kk', 'B': 'bos', 'C': 2004, 'D': 2017},
            {'A': 'ab', 'B': 'ny', 'C': 1977, 'D': 2019},
            {'A': 'fc', 'B': 'dc', 'C': 2001, 'D': 2005},
            {'A': 'cc', 'B': 'dc', 'C': 2006, 'D': 2019},
            {'A': 'et', 'B': 'la', 'C': 1995, 'D': 2005},
            {'A': 'tr', 'B': 'la', 'C': 1997, 'D': 2006},
        ])
    print("df_two")
    print(df_two)
    

    合并 B 列上的数据框:

    df_merged = pd.merge(df_one, df_two, on='B')
    print("df_merged")
    print(df_merged)
    

    执行你的逻辑:

    df_merged['D_x'] = df_merged.apply(lambda x: x['A_y'] if x['C_y'] <= x['C_x'] <= x['D_y'] else '', axis=1)
    print(df_merged)
    

    仅获取所需的列:

    result_columns = ['A_x', 'B', 'C_x', 'D_x']
    df_result = df_merged[result_columns]
    

    将列重命名为所需的格式:

    df_result = df_result.rename(columns={'A_x': 'A', 'C_x': 'C', 'D_x': 'D'})
    

    清空值为D的记录:

    df_result = df_result[df_result['D'] != '']
    print("df_result")
    print(df_result)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-24
      • 2016-04-14
      • 1970-01-01
      • 2014-01-03
      • 1970-01-01
      相关资源
      最近更新 更多