第34单元 组合数据
使用series或frame时,有用的数据可能存在于多个frame中,因此可能需要组合数据以备进一步处理。pandas提供了合并和连接frame的函数——你只需要判断是否需要合并或连接。
合并
frame的合并类似于数据库表的合并:pandas将左侧和右侧frame中具有相同索引(或其他指定列中具有相同值)的行组合在一起。如果左侧frame与右侧frame中相匹配的行是唯一的,则称该类型的合并为一对一合并。当有多个匹配时,该类型的合并称为一对多合并。对于一对多合并而言,pandas会根据需要复制左侧frame的行,而复制可能会导致行的重复(我们将在下一小节介绍如何处理重复的行)。当两个frame中都有多行相匹配时,这种合并类型称为多对多合并,而pandas还是会根据需要进行行复制,并将numpy.nans插入缺失数据的单元。
如果两个frame具有一个名称相同的列(即键列),就可以将该列上的frame合并。即使没有这样的列,也可以指定其他列作为键,如下所示:
df = pd.merge(df1, df2, on="key") df = pd.merge(df1, df2, left_on="key1", right_on="key2")
使用美国人口普查局截至2009年7月1日的数据5,建立一个关于美国人口的frame。除了包含每个州的人口数据,该frame还包含美国东部、东北部、西北部、中西部、西部和南部,以及整个美国的人口数据。
5www.census.gov/popest/data/historical/2000s/vintage_2009/state.html
population.head() ➾ Population ➾ State ➾ Wyoming 544270 ➾ District of Columbia 599657 ➾ Vermont 621760 ➾ North Dakota 646844 ➾ Alaska 698473
population和alco2009这两个frame都具有“State”索引,因此可以将索引删除,把两个frame在公共列上的所有内容合并,同时观察酒的消费量和人口数量:
df = pd.merge(alco2009.reset_index(), population.reset_index()).set_index("State") df.head() ➾ Beer Wine Spirits Population ➾ State ➾ Alabama 1.20 0.22 0.58 4708708 ➾ Alaska 1.31 0.54 1.16 698473 ➾ Arizona 1.19 0.38 0.74 6595778 ➾ Arkansas 1.07 0.17 0.60 2889450 ➾ California 1.05 0.55 0.73 36961664
如果两个frame中有相同名称的列,则pandas会将后缀"_l"和"_r"添加到列名称中。使用可选参数suffixes(两个字符串组成的元组)控制后缀。如果要在索引列而不是一般的列上合并,请使用可选参数left_index=True和right_index=True(可以同时使用或单独使用)。以下语句的结果与之前的相同,但默认的排序顺序可能存在差异:
df = pd.merge(alco2009, population, left_index=True, right_index=True) df.head() ➾ Beer Wine Spirits Population ➾ State ➾ Wyoming 1.45 0.22 1.10 544270 ➾ District of Columbia 1.26 1.00 1.64 599657 ➾ Vermont 1.36 0.63 0.70 621760 ➾ North Dakota 1.63 0.25 1.16 646844 ➾ Alaska 1.31 0.54 1.16 698473
如果两个索引都是键,就要使用join()函数替换上述的merge()函数:
population.join(alco2009).tail(10) ➾ Population Beer Wine Spirits ➾ State ➾ Illinois 12910409 1.22 0.39 0.73 ➾ Florida 18537969 1.21 0.48 0.92 ➾ New York 19541453 0.91 0.46 0.69 ➾ Texas 24782302 1.42 0.28 0.58 ➾ California 36961664 1.05 0.55 0.73 ➾ Northeast 55283679 NaN NaN NaN ➾ Midwest 66836911 NaN NaN NaN ➾ West 71568081 NaN NaN NaN ➾ South 113317879 NaN NaN NaN ➾ United States 307006550 NaN NaN NaN
join()和merge()这两个函数使用同一个可选参数how,它的可接受值为"left"(join()函数的默认值)、"right"、"inner"(merge()函数的默认值)或"outer"。左连接使用调用函数的frame(即左侧frame)的索引。右连接使用作为参数的frame(即右侧frame)的索引。外连接使用索引的并集。内连接使用索引的交集。(pandas的连接类型与先前在第18单元中介绍的MySQL连接类型一致。)
如果frame的索引不相同,则左连接(或合并)、右连接(或合并)和外连接(或合并)操作将引入具有缺失值的行。在上述例子中,这种情况发生在啤酒、葡萄酒和烈酒的总量未知的地方。内连接(或合并)不会引入新的缺失值。
如果两个frame具有名称相同的列,则必须提供可选参数lsuffix和rsuffix(这两个参数都是字符串)。pandas会将后缀附加到公共的列名称之后。
join()函数还可以使用可选参数on,实现在共享的列名称上连接两个frame(但不能用名称不同的列,或者一个是列而另一个是索引)。
连接
concat()函数通过将一组frame彼此“竖直”(axis=0,默认值)或“水平”(axis=1)地放置在一起来连接它们,并返回一个新的frame:
pd.concat([alco2009, population], axis=1).tail() ➾ Beer Wine Spirits Population ➾ Washington 1.09 0.51 0.74 6664195 ➾ West NaN NaN NaN 71568081 ➾ West Virginia 1.24 0.10 0.45 1819777 ➾ Wisconsin 1.49 0.31 1.16 5654774 ➾ Wyoming 1.45 0.22 1.10 544270
如果frame的维度不匹配,pandas就会在所谓的“空位”处加入具有缺失值的行或列。
pandas忠实地保留所有竖直堆叠的frame的索引,这可能导致索引出现重复的键。这并不妨碍你的使用,当然你也可以选择删除重复的项(具体方法将在下一小节介绍),或者通过可选参数keys(字符串列表),给新的frame添加二级索引,从而形成分层索引。对于“水平”方向的(逐列的)连接,可以使用相同的参数创建分层列名。
我们使用加拿大统计局网站6的数据,创建一个关于2011年加拿大省份人口的frame。接下来我们就可以创建一个新的frame来描述北美国家人口,结合美国和加拿大的两个人口的frame,可以给出一个合适的新索引。(请注意,美国的frame比加拿大的早两年。)
6www.statcan.gc.ca/tables-tableaux/sum-som/l01/cst01/demo02a-eng.htm
pop_na = pd.concat([population, pop_ca], keys=["US", "CA"]) pop_na.index.names = ("Country", "State") ➾ Population ➾ Country State ➾ US Wyoming 544270 ➾ District of Columbia 599657 ➾ Vermont 621760 ➾ North Dakota 646844 ➾ Alaska 698473 ➾ «...» ➾ CA Alberta 3790200 ➾ British Columbia 4499100 ➾ Yukon 35400 ➾ Northwest Territories 43500 ➾ Nunavut 34200
请记住,必要时,分层索引可以被扁平化。
两个frame应该进行合并还是连接呢?
merge()和concat()都可以将两个或多个frame组合在一起。concat()用于组合具有相似内容的frame(比如美国各州和加拿大各省的人口:“苹果到苹果”),而merge()则用于组合具有互补内容的frame(比如人口和酒精消费率:“苹果到橘子”)。
删除重复行
函数duplicated([subset])返回一个布尔型的series,表示在所有列或subset表示的列中是否有重复的行(subset是一个列名称组成的序列)。可选参数keep用于控制标记的重复行是第一个重复行("first")、最后一个重复行("last"),还是每个(True)重复行都标记。
函数drop_duplicates()返回一个删除了所有列或subset表示的列中重复行的frame或series(subset是一个列名称组成的序列)。可选参数keep用于控制删除的行是第一个重复行("frist")、最后一个重复行("last"),还是每个(True)重复行都删除。使用可选参数inplace=True可以从原始对象中删除重复项。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论