
本教程详细阐述了如何使用Python Pandas库,在两个DataFrame之间进行条件合并。当合并键存在于一个DataFrame的字符串列中,且需要提取数字部分与另一个DataFrame的索引或数字列匹配时,本教程提供了一种高效的解决方案。通过str.extract方法提取关键数字,并结合map函数实现精确的数据映射,从而避免了低效的循环操作,确保了代码的性能与可读性。
场景描述
在数据处理过程中,我们经常会遇到需要将两个数据集(dataframe)进行合并或关联的情况。然而,合并键的格式可能不尽相同,例如,一个dataframe的键是“1st”、“2nd”这样的字符串,而另一个dataframe的键是纯数字(1、2、3)。在这种情况下,直接使用merge函数可能无法达到预期效果,需要对键进行预处理。
假设我们有两个DataFrame,df1和df2,结构如下:
df1
9/30/18951st7/23/18841st3/29/18892nd4/10/18683rd4/8/18922nd
df2
11929-05-1621930-04-0331930-11-05
我们的目标是根据df1中的ceremony_number列(例如,从“1st”中提取“1”)与df2的索引(或一个名为index的列)进行匹配,然后将df2中的dates列添加到df1中,作为新的date_oscar列。
数据准备
首先,我们创建示例DataFrame并进行基本的数据类型转换,特别是日期列,将其转换为Pandas的datetime对象,这有助于后续的数据操作和一致性。
import pandas as pd# 创建 df1data1 = { 'birthdate': {0: '9/30/1895', 1: '7/23/1884', 2: '3/29/1889', 3: '4/10/1868', 4: '4/8/1892'}, 'ceremony_number': {0: '1st', 1: '1st', 2: '2nd', 3: '3rd', 4: '2nd'}}df1 = pd.DataFrame(data1)# 创建 df2# 注意:df2的键是其索引,而不是一个单独的列data2 = {'dates': {1: '1929-05-16', 2: '1930-04-03', 3: '1930-11-05'}}df2 = pd.DataFrame(data2)# 将日期列转换为datetime对象df1['birthdate'] = pd.to_datetime(df1['birthdate'], format='%m/%d/%Y')df2['dates'] = pd.to_datetime(df2['dates'], format='%Y-%m-%d')print("原始 df1:")print(df1)print("n原始 df2:")print(df2)
输出:
原始 df1: birthdate ceremony_number0 1895-09-30 1st1 1884-07-23 1st2 1889-03-29 2nd3 1868-04-10 3rd4 1892-04-08 2nd原始 df2: dates1 1929-05-162 1930-04-033 1930-11-05
核心解决方案:提取与映射
解决此问题的关键在于两个步骤:
从df1[‘ceremony_number’]字符串中提取数字。使用提取出的数字作为键,将df2[‘dates’]的值映射到df1的新列中。
# 步骤1: 从 'ceremony_number' 列中提取数字# 使用正则表达式 '^(d+)' 匹配字符串开头的连续数字# expand=False 确保返回一个 Series 而不是 DataFrame# astype(int) 将提取到的字符串数字转换为整数类型,以便与 df2 的索引匹配extracted_numbers = df1['ceremony_number'].str.extract('^(d+)', expand=False).astype(int)# 步骤2: 使用 map 函数将 df2['dates'] 的值映射到 df1# map 方法接收一个 Series 或字典。当传入一个 Series 时,# map 会使用该 Series 的索引作为查找键,Series 的值作为映射结果。# 在这里,extracted_numbers 的每个值会作为键去 df2['dates'] 的索引中查找对应的值。df1['date_oscar'] = extracted_numbers.map(df2['dates'])print("n合并后的 df1:")print(df1)
输出:
合并后的 df1: birthdate ceremony_number date_oscar0 1895-09-30 1st 1929-05-161 1884-07-23 1st 1929-05-162 1889-03-29 2nd 1930-04-033 1868-04-10 3rd 1930-11-054 1892-04-08 2nd 1930-04-03
关键技术解析
Series.str.extract(pat, expand=False):这是一个强大的字符串方法,用于从Series中的每个字符串元素中提取匹配正则表达式pat的子串。^(d+) 是一个正则表达式:^ 匹配字符串的开头。d+ 匹配一个或多个数字。() 创建一个捕获组,这意味着我们只提取括号内的内容。expand=False 参数确保返回一个Series,其中包含每个匹配的第一个捕获组。如果设置为True,则会返回一个DataFrame。Series.astype(int):将Series中的元素数据类型转换为整数。这是必要的,因为str.extract返回的是字符串,而df2的索引是整数。Series.map(arg):map方法是Pandas中用于元素级映射的利器。当arg是一个Series时,map会使用调用Series(这里是extracted_numbers)中的值作为键,去arg的索引中查找对应的值。如果某个键在arg的索引中找不到,则对应的结果将是NaN。
替代方案与注意事项
虽然map方法在此场景下非常高效和简洁,但也可以考虑其他方法:
DataFrame.merge():
如果df2的匹配键是一个常规列(而不是索引),或者需要进行更复杂的合并类型(如内连接、左连接等),merge会是更通用的选择。在使用merge之前,同样需要对df1[‘ceremony_number’]进行预处理,提取出数字,并可能需要重置df2的索引使其成为一个常规列。例如:
# df2_temp = df2.reset_index().rename(columns={'index': 'ceremony_index'})# df1['temp_key'] = df1['ceremony_number'].str.extract('^(d+)', expand=False).astype(int)# merged_df = pd.merge(df1, df2_temp, left_on='temp_key', right_on='ceremony_index', how='left')# df1['date_oscar'] = merged_df['dates']# df1.drop(columns=['temp_key'], inplace=True)
可以看出,map在添加单一列的场景下更为直接。
性能考量:
避免使用Python原生的for循环遍历DataFrame行,因为这通常效率低下,尤其对于大型数据集。Pandas的str访问器和map等方法都是高度优化的矢量化操作,能够显著提高性能。
缺失值处理:
如果extracted_numbers中的某个值在df2[‘dates’]的索引中找不到对应的项,map操作会自动填充NaN(Not a Number)值。在实际应用中,你可能需要进一步处理这些NaN值,例如填充默认值或删除包含NaN的行。
总结
本教程展示了如何利用Pandas的str.extract和map方法,高效地解决两个DataFrame之间基于字符串键提取数字进行数据关联的问题。这种方法不仅代码简洁,而且由于使用了Pandas的矢量化操作,性能也远优于传统的循环处理方式。掌握这些技巧,将有助于你更灵活、高效地处理复杂的数据合并任务。
以上就是使用Pandas高效合并DataFrame:基于字符串键提取与映射的教程的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1369993.html
微信扫一扫
支付宝扫一扫