首页 > 解决方案 > 基于另一个新数据框更新数据框

问题描述

我有 2 个数据框,其结构方式如下:

df1 = pd.read_csv("Main_Database.csv")
# df1 Columns: ..., Timestamp, Name, Query, Website, Status,...

df2 = pd.read_csv("New_Raw_Results.csv")
# df2 COlumns: ..., Timestamp, Name, Query, Website, Status,...

两个数据框可以具有完全相同的列。

Main_database.csv跟踪所有记录,我new_raw_results是每周出现的新结果的列表。我想main_database根据 3 个场景来处理我的更改:

A) IF Query AND Website in DF2 found in DF1, --> 在 DF1 列“Last Seen”中写入,使用来自 Df2 的 Timestamp --> Overwrite Status to"STILL ACTIVE"

B)如果在DF1中找不到DF2中的查询和网站,-->将整个df2.row附加到df1-->覆盖状态到"NET NEW"

C) IF Query AND Website in DF1 not found in DF2, --> Overwrite Status to"EXPIRED"

我尝试过使用合并和连接的组合,但我被困在这里。例如,如果我在一个新的数据框中隔离了这两个表之间的内部连接的结果,我不确定如何使用它来对我的主数据库执行操作。我试图在一个函数下适应所有这些条件,所以我可以使用这个函数来处理新条目。

您将如何构建此功能?解决这个问题的最简洁的方法是什么?

标签: pythondataframe

解决方案


数据集

import pandas as pd
from numpy.random import default_rng
rng = default_rng()

columns = ['query','website','timestamp','status','last_seen']
data = rng.integers(1,20,(100,5))
df1 = pd.DataFrame(data=data, columns=columns,dtype=str)
data = rng.integers(1,20,(100,5))
df2 = pd.DataFrame(data=data, columns=columns,dtype=str)

连接querywebsite列将有助于比较。例如

      Query   Website
  0  query1  website1  --> 'query1website1'

为连接列的每个 DataFrame 创建一个系列

a = df2['query'].str.cat(df2.website)
b = df1['query'].str.cat(df1.website)

为您的三个条件中的每一个创建一个布尔系列。

cond1 = a.isin(b)    # ended up not using this
cond2 = ~cond1
cond3 = ~b.isin(a)

根据条件 3 设置状态 - 您的C)

df1.loc[cond3,'status'] = 'EXPIRED'

更新新信息 - 您的A)

使用 numpy广播将所有 df2 值 ( a) 与所有 df1 值 ( ) 进行比较,并获取它们匹配的索引。b

indices1 = (a.values[:,None] == b.values).argmax(1)

(a.values[:,None] == b.values)产生一个二维布尔数组,它是每个a值与每个b值的比较。该argmax函数返回它们匹配的索引。

# df1 row indices where df1.qw == df2.qw
x = indices1[indices1 > 0]
# df2 rows where df2.qw == df1.qw
y = df2.loc[np.where(indices1 > 0)]

xdf1是在中具有匹配项的整数索引数组df2。是与(的子集)对应的匹配y项的 DataFrame 。使用整数数组将新值分配给正确的行。xdf2df1

df1.loc[x,'last_seen'] = y.timestamp.values
df1.loc[x,'status'] = "STILL ACTIVE"

警告:如果 df1 具有相同值的多行qw, np.argmax 将只找到第一行,而第二行的列保持不变。使用随机数据会定期出现。


添加新行 - 您的B)

df2.loc[cond2,'status'] = "NET NEW"
df1 = pd.concat([df1,df2.loc[cond2]], ignore_index=True)

完全的...

a = df2['query'].str.cat(df2.website)
b = df1['query'].str.cat(df1.website)

cond1 = a.isin(b)    # ended up not using this
cond2 = ~cond1
cond3 = ~b.isin(a)

df1.loc[cond3,'status'] = 'EXPIRED'

indices1 = (a.values[:,None] == b.values).argmax(1)
x = indices1[indices1 > 0]
y = df2.loc[np.where(indices1 > 0)]

df1.loc[x,'last_seen'] = y.timestamp.values
df1.loc[x,'status'] = "STILL ACTIVE"

df2.loc[cond2,'status'] = "NET NEW"
df1 = pd.concat([df1,df2.loc[cond2]], ignore_index=True)

推荐阅读