Pandas:如何通过保留第一个数据框的信息来合并同一列上的两个数据框?

2024-11-26 08:37:00
admin
原创
188
摘要:问题描述:我有两个数据框df1,df2。df1包含人员年龄的信息,df2包含人员性别的信息。 并非所有人都在df1或不在df2df1 Name Age 0 Tom 34 1 Sara 18 2 Eva 44 3 Jack 27 4 L...

问题描述:

我有两个数据框df1df2df1包含人员年龄的信息,df2包含人员性别的信息。 并非所有人都在df1或不在df2

df1
     Name   Age 
0     Tom    34
1     Sara   18
2     Eva    44
3     Jack   27
4     Laura  30

df2
     Name      Sex 
0     Tom       M
1     Paul      M
2     Eva       F
3     Jack      M
4     Michelle  F

如果 中没有这些信息,我希望在df1和 设置中获得人物的性别信息。我尝试这样做,但我保留了一些我不想要的人的信息。NaN`df2df1 = pd.merge(df1, df2, on = 'Name', how = 'outer')df2`

df1
     Name   Age     Sex
0     Tom    34      M
1     Sara   18     NaN
2     Eva    44      F
3     Jack   27      M
4     Laura  30     NaN

解决方案 1:

Sample

df1 = pd.DataFrame({'Name': ['Tom', 'Sara', 'Eva', 'Jack', 'Laura'], 
                    'Age': [34, 18, 44, 27, 30]})

#print (df1)
df3 = df1.copy()

df2 = pd.DataFrame({'Name': ['Tom', 'Paul', 'Eva', 'Jack', 'Michelle'], 
                    'Sex': ['M', 'M', 'F', 'M', 'F']})
#print (df2)

由 创建map者使用:Series`set_index`

df1['Sex'] = df1['Name'].map(df2.set_index('Name')['Sex'])
print (df1)
    Name  Age  Sex
0    Tom   34    M
1   Sara   18  NaN
2    Eva   44    F
3   Jack   27    M
4  Laura   30  NaN

采用左连接的替代解决方案merge

df = df3.merge(df2[['Name','Sex']], on='Name', how='left')
print (df)
    Name  Age  Sex
0    Tom   34    M
1   Sara   18  NaN
2    Eva   44    F
3   Jack   27    M
4  Laura   30  NaN

如果需要按多列映射(例如YearCode),需要merge使用左连接:

df1 = pd.DataFrame({'Name': ['Tom', 'Sara', 'Eva', 'Jack', 'Laura'], 
                    'Year':[2000,2003,2003,2004,2007],
                    'Code':[1,2,3,4,4],
                    'Age': [34, 18, 44, 27, 30]})

print (df1)
    Name  Year  Code  Age
0    Tom  2000     1   34
1   Sara  2003     2   18
2    Eva  2003     3   44
3   Jack  2004     4   27
4  Laura  2007     4   30

df2 = pd.DataFrame({'Name': ['Tom', 'Paul', 'Eva', 'Jack', 'Michelle'], 
                    'Sex': ['M', 'M', 'F', 'M', 'F'],
                    'Year':[2001,2003,2003,2004,2007],
                    'Code':[1,2,3,5,3],
                    'Val':[21,34,23,44,67]})
print (df2)
       Name Sex  Year  Code  Val
0       Tom   M  2001     1   21
1      Paul   M  2003     2   34
2       Eva   F  2003     3   23
3      Jack   M  2004     5   44
4  Michelle   F  2007     3   67
#merge by all columns
df = df1.merge(df2, on=['Year','Code'], how='left')
print (df)
  Name_x  Year  Code  Age Name_y  Sex   Val
0    Tom  2000     1   34    NaN  NaN   NaN
1   Sara  2003     2   18   Paul    M  34.0
2    Eva  2003     3   44    Eva    F  23.0
3   Jack  2004     4   27    NaN  NaN   NaN
4  Laura  2007     4   30    NaN  NaN   NaN

#specified columns - columns for join (Year, Code) need always + appended columns (Val)
df = df1.merge(df2[['Year','Code', 'Val']], on=['Year','Code'], how='left')
print (df)
    Name  Year  Code  Age   Val
0    Tom  2000     1   34   NaN
1   Sara  2003     2   18  34.0
2    Eva  2003     3   44  23.0
3   Jack  2004     4   27   NaN
4  Laura  2007     4   30   NaN

如果出现错误,map则意味着连接的列有重复,如下所示Name

df1 = pd.DataFrame({'Name': ['Tom', 'Sara', 'Eva', 'Jack', 'Laura'], 
                    'Age': [34, 18, 44, 27, 30]})

print (df1)
    Name  Age
0    Tom   34
1   Sara   18
2    Eva   44
3   Jack   27
4  Laura   30

df3, df4 = df1.copy(), df1.copy()

df2 = pd.DataFrame({'Name': ['Tom', 'Tom', 'Eva', 'Jack', 'Michelle'], 
                    'Val': [1,2,3,4,5]})
print (df2)
       Name  Val
0       Tom    1 <-duplicated name Tom
1       Tom    2 <-duplicated name Tom
2       Eva    3
3      Jack    4
4  Michelle    5

s = df2.set_index('Name')['Val']
df1['New'] = df1['Name'].map(s)
print (df1)

InvalidIndexError:仅对具有唯一值的 Index 对象重新编制索引才有效

解决方案是通过 删除重复项DataFrame.drop_duplicates,或者使用 mapdict进行最后的重复匹配:

#default keep first value
s = df2.drop_duplicates('Name').set_index('Name')['Val']
print (s)
Name
Tom         1
Eva         3
Jack        4
Michelle    5
Name: Val, dtype: int64

df1['New'] = df1['Name'].map(s)
print (df1)
    Name  Age  New
0    Tom   34  1.0
1   Sara   18  NaN
2    Eva   44  3.0
3   Jack   27  4.0
4  Laura   30  NaN
#add parameter for keep last value 
s = df2.drop_duplicates('Name', keep='last').set_index('Name')['Val']
print (s)
Name
Tom         2
Eva         3
Jack        4
Michelle    5
Name: Val, dtype: int64

df3['New'] = df3['Name'].map(s)
print (df3)
    Name  Age  New
0    Tom   34  2.0
1   Sara   18  NaN
2    Eva   44  3.0
3   Jack   27  4.0
4  Laura   30  NaN
#map by dictionary
d = dict(zip(df2['Name'], df2['Val']))
print (d)
{'Tom': 2, 'Eva': 3, 'Jack': 4, 'Michelle': 5}

df4['New'] = df4['Name'].map(d)
print (df4)
    Name  Age  New
0    Tom   34  2.0
1   Sara   18  NaN
2    Eva   44  3.0
3   Jack   27  4.0
4  Laura   30  NaN

解决方案 2:

也可以使用join如下方法:

df1.set_index("Name").join(df2.set_index("Name"), how="left")

编辑:添加set_index("Name")

解决方案 3:

重新索引尚未提及,但它非常快,并且可以根据需要自动填充缺失的值。


DataFrame.reindex

使用公共键(Name)作为映射数据框的索引(df2):

  • 如果df2的索引已经是Name,则reindex直接:

df2['Sex'].reindex(df1['Name'])
  • 否则set_index事先:

df2.set_index('Name')['Sex'].reindex(df1['Name'])

请注意,当分配到现有数据框时,重新索引的索引将错位,因此仅分配数组值:

df1['Sex'] = df2.set_index('Name')['Sex'].reindex(df1['Name']).array

#     Name  Age  Sex
# 0    Tom   34    M
# 1   Sara   18  NaN
# 2    Eva   44    F
# 3   Jack   27    M
# 4  Laura   30  NaN

另外,我注意到一个普遍的假设,即重新索引很慢,但实际上它很快(最快):

重新索引时间


填充缺失值

reindex支持自动填充缺失值:

  • fill_value静态替换

  • method算法替换(ffill,,bfillnearest)给定单调指数

例如,使用“不想说(PNS)”填充空Sex值:

df2.set_index('Name')['Sex'].reindex(df1['Name'], fill_value='PNS')

#     Name  Age  Sex
# 0    Tom   34    M
# 1   Sara   18  PNS
# 2    Eva   44    F
# 3   Jack   27    M
# 4  Laura   30  PNS

重新索引fill_value比链接更快fillna

使用 fillna 定时重新索引


处理重复项

映射数据框(df2)不能有重复的键,因此drop_duplicates如果适用:

df2.drop_duplicates('Name').set_index('Name')['Sex'].reindex(df1['Name'])

时间数据:

显示代码片段

'''
Note: This is python code in a js snippet, so "run code snippet" will not work.
The snippet is just to avoid cluttering the main post with supplemental code.
'''

df1 = pd.DataFrame({'Name': np.arange(n), 'Age': np.random.randint(100, size=n)}).sample(frac=1).reset_index(drop=True)
df2 = pd.DataFrame({'Name': np.arange(n) + int(n * 0.5), 'Sex': np.random.choice(list('MF'), size=n)}).sample(frac=1).reset_index(drop=True)

def reindex_(df1, df2):
    df1['Sex'] = df2.set_index('Name')['Sex'].reindex(df1['Name']).array
    return df1

def map_(df1, df2):
    df1['Sex'] = df1['Name'].map(df2.set_index('Name')['Sex'])
    return df1

def dict_(df1, df2):
    df1['Sex'] = df1['Name'].map(dict(zip(df2['Name'], df2['Sex'])))
    return df1

def merge_(df1, df2):
    return df1.merge(df2[['Name', 'Sex']], left_on='Name', right_on='Name', how='left')

def join_(df1, df2):
    return df1.set_index('Name').join(df2.set_index('Name'), how='left').reset_index()

reindex_fill_value_ = lambda df1, df2: df2.set_index('Name')['Sex'].reindex(df1['Name'], fill_value='PNTS')
reindex_fillna_ = lambda df1, df2: df2.set_index('Name')['Sex'].reindex(df1['Name']).fillna('PNTS')
map_fillna_ = lambda df1, df2: df1['Name'].map(df2.set_index('Name')['Sex']).fillna('PNTS')

Run code snippetHide resultsExpand snippet

解决方案 4:

对@jezrael 答案进行简单补充,以便从数据框创建字典。

这可能会有帮助。

Python:

df1 = pd.DataFrame({'Name': ['Tom', 'Sara', 'Eva', 'Jack', 'Laura'],
                    'Age': [34, 18, 44, 27, 30]})


df2 = pd.DataFrame({'Name': ['Tom', 'Paul', 'Eva', 'Paul', 'Jack', 'Michelle', 'Tom'],
                    'Something': ['M', 'M', 'F', 'M', 'A', 'F', 'B']})


df1_dict = pd.Series(df1.Age.values, index=df1.Name).to_dict()

df2['Age'] = df2['Name'].map(df1_dict)

print(df2)

输出:

      Name Something   Age
0       Tom         M  34.0
1      Paul         M   NaN
2       Eva         F  44.0
3      Paul         M   NaN
4      Jack         A  27.0
5  Michelle         F   NaN
6       Tom         B  34.0
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   1565  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1354  
  信创国产芯片作为信息技术创新的核心领域,对于推动国家自主可控生态建设具有至关重要的意义。在全球科技竞争日益激烈的背景下,实现信息技术的自主可控,摆脱对国外技术的依赖,已成为保障国家信息安全和产业可持续发展的关键。国产芯片作为信创产业的基石,其发展水平直接影响着整个信创生态的构建与完善。通过不断提升国产芯片的技术实力、产...
国产信创系统   21  
  信创生态建设旨在实现信息技术领域的自主创新和安全可控,涵盖了从硬件到软件的全产业链。随着数字化转型的加速,信创生态建设的重要性日益凸显,它不仅关乎国家的信息安全,更是推动产业升级和经济高质量发展的关键力量。然而,在推进信创生态建设的过程中,面临着诸多复杂且严峻的挑战,需要深入剖析并寻找切实可行的解决方案。技术创新难题技...
信创操作系统   27  
  信创产业作为国家信息技术创新发展的重要领域,对于保障国家信息安全、推动产业升级具有关键意义。而国产芯片作为信创产业的核心基石,其研发进展备受关注。在信创国产芯片的研发征程中,面临着诸多复杂且艰巨的难点,这些难点犹如一道道关卡,阻碍着国产芯片的快速发展。然而,科研人员和相关企业并未退缩,积极探索并提出了一系列切实可行的解...
国产化替代产品目录   28  
热门文章
项目管理软件有哪些?
云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用