问题描述
我有两个数据帧 df1
和 df2
.df1
包含人的年龄信息,而df2
包含人的性别信息.并非所有人都在 df1
或 df2
df1姓名年龄0 汤姆 341 萨拉 182 伊娃 443 杰克 274 劳拉 30df2姓名性别0 汤姆1 保罗2 伊娃3 杰克米4 米歇尔 F
我想在df1
中获取人的性别信息,如果df2
中没有此信息,则设置NaN
.我试着做 df1 = pd.merge(df1, df2, on = 'Name', how = 'outer')
但我把一些人的信息保存在 df2
我不想要的.
df1姓名 年龄 性别0 汤姆 34 米1 萨拉 18 南2 伊娃 44 华氏度3 杰克 27 M4 劳拉 30 南
Sample
:
df1 = pd.DataFrame({'Name': ['Tom', 'Sara', 'Eva', 'Jack', 'Laura'],'年龄': [34, 18, 44, 27, 30]})#打印(df1)df3 = df1.copy()df2 = pd.DataFrame({'Name': ['Tom', 'Paul', 'Eva', 'Jack', 'Michelle'],'性别': ['M', 'M', 'F', 'M', 'F']})#打印(df2)
使用map
由 Series
创建,由 set_index
:
df1['Sex'] = df1['Name'].map(df2.set_index('Name')['Sex'])打印 (df1)姓名 年龄 性别0 汤姆 34 米1 萨拉 18 南2 伊娃 44 华氏度3 杰克 27 M4 劳拉 30 南
使用 merge
左连接:
df = df3.merge(df2[['Name','Sex']], on='Name', how='left')打印 (df)姓名 年龄 性别0 汤姆 34 米1 萨拉 18 南2 伊娃 44 华氏度3 杰克 27 M4 劳拉 30 南
如果需要按多列映射(例如Year
和Code
)需要merge
与左连接:
df1 = pd.DataFrame({'Name': ['Tom', 'Sara', 'Eva', 'Jack', 'Laura'],'年':[2000,2003,2003,2004,2007],'代码':[1,2,3,4,4],'年龄': [34, 18, 44, 27, 30]})打印 (df1)姓名 年份 代码 年龄0 汤姆 2000 1 341 萨拉 2003 2 182 伊娃 2003 3 443 杰克 2004 4 274 劳拉 2007 4 30df2 = pd.DataFrame({'Name': ['Tom', 'Paul', 'Eva', 'Jack', 'Michelle'],'性别': ['M', 'M', 'F', 'M', 'F'],'年':[2001,2003,2003,2004,2007],'代码':[1,2,3,5,3],'瓦尔':[21,34,23,44,67]})打印 (df2)姓名 性别 年份 代码 Val0 汤姆 M 2001 1 211 保罗 M 2003 2 342 伊娃 F 2003 3 233 杰克 M 2004 5 444 米歇尔 F 2007 3 67
#merge 按所有列df = df1.merge(df2, on=['Year','Code'], how='left')打印 (df)Name_x 年份代码 年龄 Name_y 性别 Val0 汤姆 2000 1 34 NaN NaN NaN1 萨拉 2003 2 18 保罗 M 34.02 伊娃 2003 3 44 伊娃 F 23.03 杰克 2004 4 27 NaN NaN NaN4 劳拉 2007 4 30 NaN NaN NaN#specified 列 - 连接列(年份、代码)需要总是 + 附加列(Val)df = df1.merge(df2[['Year','Code','Val']], on=['Year','Code'], how='left')打印 (df)姓名 年份 代码 年龄 Val0 汤姆 2000 1 34 NaN1 萨拉 2003 2 18 34.02 伊娃 2003 3 44 23.03 杰克 2004 4 27 NaN4 劳拉 2007 4 30 NaN
如果 map
出现错误,则表示按连接列重复,这里是 Name
:
df1 = pd.DataFrame({'Name': ['Tom', 'Sara', 'Eva', 'Jack', 'Laura'],'年龄': [34, 18, 44, 27, 30]})打印 (df1)姓名年龄0 汤姆 341 萨拉 182 伊娃 443 杰克 274 劳拉 30df3, df4 = df1.copy(), df1.copy()df2 = pd.DataFrame({'Name': ['Tom', 'Tom', 'Eva', 'Jack', 'Michelle'],'瓦尔':[1,2,3,4,5]})打印 (df2)名称瓦尔0 Tom 1 <-重复名称 Tom1 Tom 2 <-重复名称 Tom2 伊娃 33 杰克 44 米歇尔 5s = df2.set_index('Name')['Val']df1['New'] = df1['Name'].map(s)打印 (df1)
InvalidIndexError:重新索引仅对唯一值的索引对象有效
解决方案通过 DataFrame 删除重复项.drop_duplicates
, 或者使用 map by dict
进行最后一次重复匹配:
#default 保留第一个值s = df2.drop_duplicates('Name').set_index('Name')['Val']印刷)姓名汤姆 1伊娃 3杰克 4米歇尔 5名称:Val,数据类型:int64df1['New'] = df1['Name'].map(s)打印 (df1)姓名 年龄 新0 汤姆 34 1.01 萨拉 18 南2 伊娃 44 3.03 杰克 27 4.04 劳拉 30 南
#add 保留最后一个值的参数s = df2.drop_duplicates('Name', keep='last').set_index('Name')['Val']印刷)姓名汤姆 2伊娃 3杰克 4米歇尔 5名称:Val,数据类型:int64df3['New'] = df3['Name'].map(s)打印 (df3)姓名 年龄 新0 汤姆 34 2.01 萨拉 18 南2 伊娃 44 3.03 杰克 27 4.04 劳拉 30 南
#map by dictionaryd = dict(zip(df2['Name'], df2['Val']))打印 (d){'汤姆':2,'伊娃':3,'杰克':4,'米歇尔':5}df4['New'] = df4['Name'].map(d)打印 (df4)姓名 年龄 新0 汤姆 34 2.01 萨拉 18 南2 伊娃 44 3.03 杰克 27 4.04 劳拉 30 南
I have two dataframes df1
and df2
. df1
contains the information of the age of people, while df2
contains the information of the sex of people. Not all the people are in df1
nor in 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
I want to have the information of the sex of the people in df1
and setting NaN
if I do not have this information in df2
. I tried to do df1 = pd.merge(df1, df2, on = 'Name', how = 'outer')
but I keep the information of some people in df2
that I don't want.
df1
Name Age Sex
0 Tom 34 M
1 Sara 18 NaN
2 Eva 44 F
3 Jack 27 M
4 Laura 30 NaN
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)
Use map
by Series
created by 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
Alternative solution with merge
with left join:
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
If need map by multiple columns (e.g. Year
and Code
) need merge
with left join:
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
If get error with map
it means duplicates by columns of join, here 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)
Solutions are removed duplicates by DataFrame.drop_duplicates
, or use map by dict
for last dupe match:
#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
这篇关于Pandas:如何通过保留第一个的信息来合并列上的两个数据帧?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!