检查表示区域的列是否包含第二个数据帧的值



我有两个数据帧,如下所示:

data = [['id', 'r0', 'r1'],
['123',   1, 6],
['436',   9, 26],
['791',  45, 200]]
df = pd.DataFrame(data)

data_2 = [['id', 'r3',   'name'],
['123',     1, 'name_a'],
['436',    12, 'name_f'],
['436',    78, 'name_q'],
['234',   300, 'name_d']]
df_2 = pd.DataFrame(data_2)

我想在 df 上包含两个额外的列,其中包含以下信息:

  • is_contained:对/错。它告诉是否有任何值,如果df_2[r3] 包含在df[id] == df_2[id]df[r0-r1]的范围内。例如,在df的前两个寄存器,它将是 True,在第三个寄存器中,它将是 将为假。
  • name:如果is_contained为 True,则复制df_2["name"].否则,此字符串将为空。

因此,这个简单示例的结果将是:

df

0   1    2             3        4
0   id  r0   r1  is_contained     name
1  123   1    6          True   name_a
2  456   9   26          True   name_f
3  791  45  200         False       

考虑到比我的真实例子,这个计算将包括一个相当大的df,这将是解决这个问题的有效方法?

如果我理解正确(并假设第一行是列名!),您可以使用pandas.merge_asof,然后计算"is_contained"列,如果它不符合上限要求,则更新"名称"。

先决条件是,确保数据帧按"r0"和"r3"排序。

(pd
.merge_asof(df, df_2, by='id', left_on='r0', right_on='r3', direction='forward')
.assign(is_contained=lambda d: d['r3'].le(d['r1']),
name=lambda d: d['name'].where(d['is_contained'])
)
#.drop(columns='r3') # optional, to remove merge column
)

输出:

id  r0   r1    r3    name  is_contained
0  123   1    6   1.0  name_a          True
1  436   9   26  12.0  name_f          True
2  791  45  200   NaN     NaN         False

使用的输入:

data = [['123',   1, 6],
['436',   9, 26],
['791',  45, 200]]
df = pd.DataFrame(data, columns=['id', 'r0', 'r1'])

data_2 = [['123',     1, 'name_a'],
['436',    12, 'name_f'],
['436',    78, 'name_q'],
['234',   300, 'name_d']]
df_2 = pd.DataFrame(data_2, columns=['id', 'r3',   'name'])

这成功了

df.to_sql("df", conn, index=False)
df_2.to_sql("df_2", conn, index=False)
query = "SELECT *"
"FROM df "
"LEFT JOIN df_2 "
"ON (df.id = df_2.id AND "
"df_2.r3 >= df.r0 AND "
"df_2.r3 <= df.r1);"
df = pd.read_sql_query(query,conn)

最新更新