Python 根据特定条件逐行合并两个快速数据帧

Python 根据特定条件逐行合并两个快速数据帧,python,pandas,merge,apply,Python,Pandas,Merge,Apply,在过去的10天里,我一直在努力解决我的问题,但我找不到一个快速有效的解决方案 情况就是这样。我有一个DF包含人力资源网站的网络流量数据。 此数据框的每一行都指向一个应用程序(即:某人通过特定的web源访问网站,并在特定时间申请特定的工作机会)。 以下是一个例子: import pandas as pd web_data = {'source': ['Google', 'Facebook','Email'], 'job_id': ['123456', '654321','0101

在过去的10天里,我一直在努力解决我的问题,但我找不到一个快速有效的解决方案

情况就是这样。我有一个DF包含人力资源网站的网络流量数据。 此数据框的每一行都指向一个应用程序(即:某人通过特定的web源访问网站,并在特定时间申请特定的工作机会)。 以下是一个例子:

import pandas as pd
web_data = {'source':  ['Google', 'Facebook','Email'],
        'job_id': ['123456', '654321','010101'],
        'd_date_hour_event' : ['2019-11-01 00:09:59','2019-11-01 00:10:41','2019-11-01 00:19:20'],
        }
web_data = pd.DataFrame(web_data)
hr_data ={'candidate_id':  ['ago23ak', 'bli78gro','123tru456'],
        'job_id': ['675848', '343434','010101'],
        'date_time_submission' : ['2019-11-10 00:24:59','2019-11-09 12:10:41','2019-11-01 00:19:22'],
         'job_label':['HR internship','Data Science Supervisor','Project Manager']
        }

hr_data = pd.DataFrame(hr_data)
在第二个数据框架中,我有一个人力资源内部工具的摘录,我们在其中收集所有收到的应用程序以及一些补充数据。以下是一个例子:

import pandas as pd
web_data = {'source':  ['Google', 'Facebook','Email'],
        'job_id': ['123456', '654321','010101'],
        'd_date_hour_event' : ['2019-11-01 00:09:59','2019-11-01 00:10:41','2019-11-01 00:19:20'],
        }
web_data = pd.DataFrame(web_data)
hr_data ={'candidate_id':  ['ago23ak', 'bli78gro','123tru456'],
        'job_id': ['675848', '343434','010101'],
        'date_time_submission' : ['2019-11-10 00:24:59','2019-11-09 12:10:41','2019-11-01 00:19:22'],
         'job_label':['HR internship','Data Science Supervisor','Project Manager']
        }

hr_data = pd.DataFrame(hr_data)
以下是我面临的困难:

  • 没有唯一的键可以用来合并这两个表。我必须使用“作业id”(对于每个作业都是唯一的)以及通过“d_日期\小时\事件”(在web_数据DF上)和“日期\时间\提交”(在hr_数据DF上)列出现应用程序的时间
  • 对于同一应用程序,在两个表上注册的时间可能不相同(相差几秒)
  • 某些web_数据值可能不在hr_数据中
最后,我想得到一个如下所示的数据帧:

for i, row in web_data.iterrows() :
    #we stock the needed value for hr_data research
    date = row.d_date_hour_event
    job = row.job_id
    
    #we compute the time period
    inf = date - timedelta(seconds=10)
    sup = date + timedelta(seconds=10)
    
    #we check if there a matching row in hr_data
    temp_df = pd.DataFrame()
    temp_df = hr_data[(hr_data.job_id == job) & \
                         (hr_data.date_time_submission >= inf) & (hr_data.date_time_submission <= sup)].tail(1)
    
    #if there is a matching row, we merge them and update web_data table
    if not temp_df.empty:
        row = row.to_frame().transpose()
        
        join = pd.merge(row, temp_df, how='inner', on='job_id',left_index=False, right_index=True)
        
        web_data.update(join)

实际上,我已经编写了实现这个合并的函数。看起来是这样的:

for i, row in web_data.iterrows() :
    #we stock the needed value for hr_data research
    date = row.d_date_hour_event
    job = row.job_id
    
    #we compute the time period
    inf = date - timedelta(seconds=10)
    sup = date + timedelta(seconds=10)
    
    #we check if there a matching row in hr_data
    temp_df = pd.DataFrame()
    temp_df = hr_data[(hr_data.job_id == job) & \
                         (hr_data.date_time_submission >= inf) & (hr_data.date_time_submission <= sup)].tail(1)
    
    #if there is a matching row, we merge them and update web_data table
    if not temp_df.empty:
        row = row.to_frame().transpose()
        
        join = pd.merge(row, temp_df, how='inner', on='job_id',left_index=False, right_index=True)
        
        web_data.update(join)
web_data.iterrows()中的i行的
:
#我们储存了人力资源数据研究所需的价值
日期=行d\u日期\u小时\u事件
job=行。job\u id
#我们计算时间周期
inf=日期-时间增量(秒=10)
sup=日期+时间增量(秒=10)
#我们检查hr\U数据中是否有匹配的行
temp_df=pd.DataFrame()
temp\u df=hr\u数据[(hr\u data.job\u id==job)和\

(hr_data.date_time_submission>=inf)和(hr_data.date_time_submission让我们分几个步骤来尝试:

1。将两个数据帧中的日期时间列转换为pd.datetime格式

web_data = web_data.assign(d_date_hour_event= lambda x: pd.to_datetime(x['d_date_hour_event']))
hr_data = hr_data.assign(date_time_submission=lambda x: pd.to_datetime(x['date_time_submission']))
2.重命名
hr\u数据
数据框的
job\u id
,以便在合并时不会提供任何错误

hr_data = hr_data.rename(columns={"job_id": "job_id_hr"})
3.从两个数据帧中包含
时间戳和
作业ID的列中创建
numpy
数组,并检查
web\u数据中的时间戳在
hr\u数据中的
时间戳
数据帧中的
时间戳
10秒内的行,并且具有相同的
job\u\id
使用
numpy
广播

web_data_dates = web_data['d_date_hour_event'].values
hr_data_dates = hr_data['date_time_submission'].values
web_data_job_ids = web_data['job_id'].values
hr_data_job_ids = hr_data['job_id_hr'].values

i, j = np.where(
    (hr_data_dates[:, None] <= (web_data_dates+pd.Timedelta(10, 'S'))) & 
    (hr_data_dates[:, None] >= (web_data_dates-pd.Timedelta(10, 'S'))) & 
    (hr_data_job_ids[:, None] == web_data_job_ids)
)

overlapping_rows = pd.DataFrame(
    np.column_stack([web_data.values[j], hr_data.values[i]]),
    columns=web_data.columns.append(hr_data.columns)
)
最后只需更新
web\u数据
dataframe(如果您不想覆盖原始数据帧,请先创建一个副本)


必须比在所有行上迭代快得多

这是我正在使用的代码(除非您做出我在注释中描述的更改,否则该代码不起作用)

web_data={'source':['Google','Facebook','Email'],
“作业id:['123456'、'654321'、'010101'],
“日期/时间/事件”:[2019-11-01 00:09:59'、'2019-11-01 00:10:41'、'2019-11-01 00:19:20',
}
web\u数据=pd.DataFrame(web\u数据)
#将“010101”和“2019-11-01 00:19:22”放在第二位,而不是像以前那样放在第三位
#如果您分别在“作业id”和“日期时间提交”数组中将这些值重新切换到第三个位置,应该可以正常工作
hr_数据={'candidate_id':['ago23ak','bli78gro','123tru456'],
“作业id:['675848'、'010101'、'343434'],
“提交日期和时间”:[2019-11-10 00:24:59'、'2019-11-01 00:19:22'、'2019-11-09 12:10:41',
“工作标签”:[“人力资源实习”、“数据科学主管”、“项目经理”]
}
hr\U数据=局部数据帧(hr\U数据)
hr\u data=hr\u data.rename(列={“作业id”:“作业id\u hr”})
web\u data=web\u data.assign(d\u date\u hour\u event=lambda x:pd.to\u datetime(x['d\u date\u hour\u event']))
hr\u data=hr\u data.assign(日期时间提交=lambda x:pd.to\u日期时间(x['date\u time\u submission']))
web\u数据\u日期=web\u数据['d\u日期\u小时\u事件']。值
hr_数据_日期=hr_数据['date_time_submission']。值
web_data_job_id=web_data['job_id']。值
hr_数据\u作业\u id=hr_数据['job_id\u hr']。值
i、 j=np.where(
(人力资源数据日期[:,无]=(网络数据日期-pd.Timedelta(10,'S'))和
(人力资源数据作业ID[:,无]==网络数据作业ID[:,无])
)
重叠行=pd.DataFrame(
np.column_stack([web_data.values[j]、hr_data.values[i]]),
columns=web\u data.columns.append(hr\u data.columns)
)
重叠行

非常感谢Rik,在我尝试你的代码之前有一些问题:抱歉,重复发帖:非常感谢Rik,在我尝试你的代码之前有一些问题:-你考虑过“双键”吗检查重叠?因为可能有很多应用程序在10秒内出现,如果我不检查job_id和job_id_hr之间的匹配,我可能会以很多重叠行结束,你不这样认为吗?我还是会尝试:)不抱歉,但很容易添加。我将更新答案:)。嘿,再次Rik,不幸的是,它不起作用。它不起作用的原因似乎与数组的大小有关。因为我的web_数据DF和hr_数据DF的大小不同(250k行与140k行),np.where不起作用。我也尝试了我提供的示例。当两个DFs的长度都为3行时,它会非常好,但当我在其中一行中添加一行时,它就不再起作用了。并且发生了一个错误==>弃用警告:elementwise比较失败;这将在将来引发一个错误。有任何措辞吗?:)thanksAlso,我没有提到这一点(但这是隐含的事实,两个DFs的大小不一样),在web_数据DF的第1000行(例如)注册的应用程序确实可能与hr_数据DF的23400行相匹配……我在测试示例中尝试了混合位置(将第三行web_数据DF的位置与第二行进行切换),即使两个DF具有相同的大小(各3行),因为第三行web_数据DF不具有相同的大小