当前位置: 首页 > news >正文

Python数据分析NumPy和pandas(二十五、数据整理--连接、合并和重塑 之二:数据连接合并操作)

pandas提供了多种方式来组合数据,常用的方法有:pandas.merge()、pandas.concat()和combine_first()等。

pandas.merge:根据一个或多个键连接 DataFrame 中的行或列。类似于数据库SQL语句的连接操作。

pandas.concat:沿轴方向将对象连接或堆叠在一起。

combine_first:将重叠的数据拼接在一起,使用一个对象中的值填充另一个对象中的缺失值。

一、DataFrame的连接

DataFrame数据集的连接操作可以通过一个或多个键(key)连接行来实现,类似于数据库的SQL join语句。例如:

import numpy as np
import pandas as pd# df1和df2的数据使用 pandas的扩展类型 Int64(用于可为空的整数)
df1 = pd.DataFrame({"key": ["b", "b", "a", "c", "a", "a", "b"],"data1": pd.Series(range(7), dtype="Int64")})
df2 = pd.DataFrame({"key": ["a", "b", "d"],"data2": pd.Series(range(3), dtype="Int64")})# many-to-one join 多对一连接
result = pd.merge(df1, df2)

df1输出:

keydata1
0b0
1b1
2a2
3c3
4a4
5a5
6b6

df2输出:

keydata2
0a0
1b1
2d2

 pd.merge(df1, df2) 按df1和df2的key进行匹配,执行行连接操作,过滤掉未匹配的行,输出:

keydata1data2
0b01
1b11
2a20
3a40
4a50
5b61

注意:在上面的代码pd.merge(df1, df2)中没有指定作为key连接的列,这种情况 pandas.merge 使用相同(重叠)的列名作为键,所以这里使用key列名作为连接键,但是最好要明确指定关联列名信息。如:pd.merge(df1, df2, on="key")。通常,pandas.merge 操作后的列输出顺序是未指定的。

如果要连接的对象没有相同的列名,我们可以用参数left_on, right_on指定关联键,例如:

import numpy as np
import pandas as pd# df3和df4的数据使用 pandas的扩展类型 Int64(用于可为空的整数)
df3 = pd.DataFrame({"lkey": ["b", "b", "a", "c", "a", "a", "b"],"data1": pd.Series(range(7), dtype="Int64")})
df4 = pd.DataFrame({"rkey": ["a", "b", "d"],"data2": pd.Series(range(3), dtype="Int64")})
# df3和df4中没有相同列名,用left_on, right_on参数指定关联列名
pd.merge(df3, df4, left_on="lkey", right_on="rkey")

df3输出:

lkeydata1
0b0
1b1
2a2
3c3
4a4
5a5
6b6

df4输出:

rkeydata2
0a0
1b1
2d2

 pd.merge(df3, df4, left_on="lkey", right_on="rkey") 输出:

lkeydata1rkeydata2
0b0b1
1b1b1
2a2a0
3a4a0
4a5a0
5b6b1

从输出结果中可以看到,缺少 “c” 和 “d” 值以及相关数据,这是因为默认情况下,pandas.merge 执行 “inner” 内连接,结果中的键是两个表中的交集。我们还可以通过how参数指定连接方式: “left”、“right” 和 “outer”(左连接、右连接和外连接)。外连接采用键的并集,例如:

import numpy as np
import pandas as pd# df1和df2的数据使用 pandas的扩展类型 Int64(用于可为空的整数)
df1 = pd.DataFrame({"key": ["b", "b", "a", "c", "a", "a", "b"],"data1": pd.Series(range(7), dtype="Int64")})
df2 = pd.DataFrame({"key": ["a", "b", "d"],"data2": pd.Series(range(3), dtype="Int64")})# df3和df4的数据使用 pandas的扩展类型 Int64(用于可为空的整数)
df3 = pd.DataFrame({"lkey": ["b", "b", "a", "c", "a", "a", "b"],"data1": pd.Series(range(7), dtype="Int64")})
df4 = pd.DataFrame({"rkey": ["a", "b", "d"],"data2": pd.Series(range(3), dtype="Int64")})# 外连接
pd.merge(df1, df2, how="outer")
pd.merge(df3, df4, left_on="lkey", right_on="rkey", how="outer")

pd.merge(df1, df2, how="outer") 输出:

keydata1data2
0a20
1a40
2a50
3b01
4b11
5b61
6c3<NA>
7d<NA>2

 pd.merge(df3, df4, left_on="lkey", right_on="rkey", how="outer") 输出:

lkeydata1rkeydata2
0a2a0
1a4a0
2a5a0
3b0b1
4b1b1
5b6b1
6c3NaN<NA>
7NaN<NA>d2

在外连接中,左侧或右侧 DataFrame 对象的行如果与关联的 DataFrame 中的键不匹配,则关联的 DataFrame 的列中将在对应行上显示 NA 值。how 参数的不同连接类型说明如下图列表:

看一个使用how="left"左连接的例子:

import numpy as np
import pandas as pd# df3和df4的数据使用 pandas的扩展类型 Int64(用于可为空的整数)
df1 = pd.DataFrame({"key": ["b", "b", "a", "c", "a", "b"],"data1": pd.Series(range(6), dtype="Int64")})
df2 = pd.DataFrame({"key": ["a", "b", "a", "b", "d"],"data2": pd.Series(range(5), dtype="Int64")})
# 以df1为主表左连接关联df2
pd.merge(df1, df2, on="key", how="left")

df1输出:

keydata1
0b0
1b1
2a2
3c3
4a4
5b5

 df2输出:

keydata2
0a0
1b1
2a2
3b3
4d4

 pd.merge(df1, df2, on="key", how="left") 输出(多对多关联形成笛卡尔积,例如,由于左侧 DataFrame 中有 3 个 “b” 行,右侧 DataFrame 中有 2 个 “b” 行,因此结果中有 6 个 “b” 行):

keydata1data2
0b01
1b03
2b11
3b13
4a20
5a22
6c3<NA>
7a40
8a42
9b51
10b53

 再看下内连接,将参数how的值设置为inner,how="inner"。

import numpy as np
import pandas as pd# df3和df4的数据使用 pandas的扩展类型 Int64(用于可为空的整数)
df1 = pd.DataFrame({"key": ["b", "b", "a", "c", "a", "b"],"data1": pd.Series(range(6), dtype="Int64")})
df2 = pd.DataFrame({"key": ["a", "b", "a", "b", "d"],"data2": pd.Series(range(5), dtype="Int64")})
# 以df1为主表左连接关联df2
pd.merge(df1, df2, on="key", how="inner")

 pd.merge(df1, df2, on="key" how="inner") 输出:

keydata1data2
0b01
1b03
2b11
3b13
4a20
5a22
6a40
7a42
8b51
9b53

how="inner" 这种连接方式只输出双方匹配上的key所在的行,去掉了双方没有匹配的c,d值。

如果要基于多个键进行合并,可以传递列名列表,如下示例:

import numpy as np
import pandas as pd# left和right的数据使用 pandas的扩展类型 Int64(用于可为空的整数)
left = pd.DataFrame({"key1": ["foo", "foo", "bar"],"key2": ["one", "two", "one"],"lval": pd.Series([1, 2, 3], dtype='Int64')})
right = pd.DataFrame({"key1": ["foo", "foo", "bar", "bar"],"key2": ["one", "one", "one", "two"],"rval": pd.Series([4, 5, 6, 7], dtype='Int64')})
pd.merge(left, right, on=["key1", "key2"], how="outer")

left输出:

key1key2lval
0fooone1
1footwo2
2barone3

right输出:

key1key2rval
0fooone4
1fooone5
2barone6
3bartwo7

 pd.merge(left, right, on=["key1", "key2"], how="outer") 输出:

key1key2lvalrval
0barone36
1bartwo<NA>7
2fooone14
3fooone15
4footwo2<NA>

注意:在进行列连接时,会丢弃传 DataFrame 对象上的索引。如果需要保留索引值,可以使用 reset_index 将索引追加到列。

合并操作中还要考虑的一个问题是:怎么处理合并对象存在相同列名的显示,例如对于上面的示例中的两个DataFrame对象left和right在key1上进行关联:

import numpy as np
import pandas as pd# df3和df4的数据使用 pandas的扩展类型 Int64(用于可为空的整数)
left = pd.DataFrame({"key1": ["foo", "foo", "bar"],"key2": ["one", "two", "one"],"lval": pd.Series([1, 2, 3], dtype='Int64')})
right = pd.DataFrame({"key1": ["foo", "foo", "bar", "bar"],"key2": ["one", "one", "one", "two"],"rval": pd.Series([4, 5, 6, 7], dtype='Int64')})#pd.merge(left, right, on=["key1", "key2"], how="outer")
pd.merge(left, right, on="key1")

pd.merge(left, right, on="key1")输出:

key1key2_xlvalkey2_yrval
0fooone1one4
1fooone1one5
2footwo2one4
3footwo2one5
4barone3one6
5barone3two7

 虽然pandas.merge默认会对重复的左右关联对象中的相同列名做处理,但是一般我们还是可以使用suffixes参数给相同列名指定后缀:

import numpy as np
import pandas as pd# df3和df4的数据使用 pandas的扩展类型 Int64(用于可为空的整数)
left = pd.DataFrame({"key1": ["foo", "foo", "bar"],"key2": ["one", "two", "one"],"lval": pd.Series([1, 2, 3], dtype='Int64')})
right = pd.DataFrame({"key1": ["foo", "foo", "bar", "bar"],"key2": ["one", "one", "one", "two"],"rval": pd.Series([4, 5, 6, 7], dtype='Int64')})pd.merge(left, right, on="key1", suffixes=("_left", "_right"))

 pd.merge(left, right, on="key1", suffixes=("_left", "_right")) 输出:

key1key2_leftlvalkey2_rightrval
0fooone1one4
1fooone1one5
2footwo2one4
3footwo2one5
4barone3one6
5barone3two7

pandas.merge()的参数见下图列表,学习过程中可以试着用一用:

上面学习的是对列的合并操作,下面接着来了解对行的合并或连接操作。

二、在索引(行)上合并

要在索引(行)上合并或连接数据,需要用到参数 left_index=True 或 right_index=True(或两者)等,以指示将索引(行)用作合并键。

import numpy as np
import pandas as pd# left1的数据使用 pandas的扩展类型 Int64(用于可为空的整数)
left1 = pd.DataFrame({"key": ["a", "b", "a", "a", "b", "c"],"value": pd.Series(range(6), dtype="Int64")})
right1 = pd.DataFrame({"group_val": [3.5, 7]}, index=["a", "b"])
pd.merge(left1, right1, left_on="key", right_index=True)

left1输出:

keyvalue
0a0
1b1
2a2
3a3
4b4
5c5

right1输出:

group_val
a3.5
b7.0

pd.merge(left1, right1, left_on="key", right_index=True) 这行代码中,用left_on="key"指示使用left1的key列作为连接键,right_index=True指示使用right1的行索引作为连接键,这行代码输出:

keyvaluegroup_val
0a03.5
1b17.0
2a23.5
3a33.5
4b47.0

从这个输出可以看出 left1的行索引(最左列0,1,2,3,4)被保留了,因为 right1 的索引是唯一的,所以这个 “多对一” 合并(使用默认的 how=“inner” 方法)可以保留 left1 中与输出中的行相对应的索引值。

由于默认的合并方法是使连接键求交集,我们也可以用外连接来形成它们的并集:

import numpy as np
import pandas as pd# left1的数据使用 pandas的扩展类型 Int64(用于可为空的整数)
left1 = pd.DataFrame({"key": ["a", "b", "a", "a", "b", "c"],"value": pd.Series(range(6), dtype="Int64")})
right1 = pd.DataFrame({"group_val": [3.5, 7]}, index=["a", "b"])
# 外连接求并集
pd.merge(left1, right1, left_on="key", right_index=True, how="outer")

pd.merge(left1, right1, left_on="key", right_index=True, how="outer") 输出(从输出也可以看出left1的行索引值被保留了):

keyvaluegroup_val
0a03.5
2a23.5
3a33.5
1b17.0
4b47.0
5c5NaN

如果对象有多层索引,处理起来会更复杂些,对于分层索引数据,因为在索引(指行索引)上连接等效于多键合并,还是看代码示例: 

import numpy as np
import pandas as pd# lefth和righth的数据都是用pandas扩展类型Int64,允许空的整数
lefth = pd.DataFrame({"key1": ["Ohio", "Ohio", "Ohio","Nevada", "Nevada"],"key2": [2000, 2001, 2002, 2001, 2002],"data": pd.Series(range(5), dtype="Int64")})
righth_index = pd.MultiIndex.from_arrays([["Nevada", "Nevada", "Ohio", "Ohio", "Ohio", "Ohio"],[2001, 2000, 2000, 2000, 2001, 2002]]
)
righth = pd.DataFrame({"event1": pd.Series([0, 2, 4, 6, 8, 10], dtype="Int64",index=righth_index),"event2": pd.Series([1, 3, 5, 7, 9, 11], dtype="Int64",index=righth_index)})pd.merge(lefth, righth, left_on=["key1", "key2"], right_index=True)

lefth输出:

key1key2data
0Ohio20000
1Ohio20011
2Ohio20022
3Nevada20013
4Nevada20024

righth输出(具有多层索引):

event1event2
Nevada200101
200023
Ohio200045
200067
200189
20021011

pd.merge(lefth, righth, left_on=["key1", "key2"], right_index=True) 这行代码传递了一个连接键列表给left_on参数指示左侧用key1, key2作为连接键,right_index=True指示右侧使用行索引作为连接键,输出:

key1key2dataevent1event2
0Ohio2000045
0Ohio2000067
1Ohio2001189
2Ohio200221011
3Nevada2001301

pd.merge(lefth, righth, left_on=["key1", "key2"], right_index=True) 这行代码我们再加上how="outer"进行外连接看看会输出什么内容:

# lefth和righth的数据都是用pandas扩展类型Int64,允许空的整数
lefth = pd.DataFrame({"key1": ["Ohio", "Ohio", "Ohio","Nevada", "Nevada"],"key2": [2000, 2001, 2002, 2001, 2002],"data": pd.Series(range(5), dtype="Int64")})
righth_index = pd.MultiIndex.from_arrays([["Nevada", "Nevada", "Ohio", "Ohio", "Ohio", "Ohio"],[2001, 2000, 2000, 2000, 2001, 2002]]
)
righth = pd.DataFrame({"event1": pd.Series([0, 2, 4, 6, 8, 10], dtype="Int64",index=righth_index),"event2": pd.Series([1, 3, 5, 7, 9, 11], dtype="Int64",index=righth_index)})
pd.merge(lefth, righth, left_on=["key1", "key2"], right_index=True, how="outer")

pd.merge(lefth, righth, left_on=["key1", "key2"], right_index=True, how="outer") 输出:

key1key2dataevent1event2
4Nevada2000<NA>23
3Nevada2001301
4Nevada20024<NA><NA>
0Ohio2000045
0Ohio2000067
1Ohio2001189
2Ohio200221011

通过how="outer"指示进行外连接,输出的是两个DataFrame的并集。 上面保留了lefth的索引,也可以合并双方的索引,如下代码示例:

import numpy as np
import pandas as pd# left2和right2的数据都是用pandas扩展类型Int64,允许空的整数
left2 = pd.DataFrame([[1., 2.], [3., 4.], [5., 6.]],index=["a", "c", "e"],columns=["Ohio", "Nevada"]).astype("Int64")
right2 = pd.DataFrame([[7., 8.], [9., 10.], [11., 12.], [13, 14]],index=["b", "c", "d", "e"],columns=["Missouri", "Alabama"]).astype("Int64")pd.merge(left2, right2, how="outer", left_index=True, right_index=True)

 left2输出:

OhioNevada
a12
c34
e56

right2输出:

MissouriAlabama
b78
c910
d1112
e1314

 pd.merge(left2, right2, how="outer", left_index=True, right_index=True) 输出:

OhioNevadaMissouriAlabama
a12<NA><NA>
b<NA><NA>78
c34910
d<NA><NA>1112
e561314

DataFrame 实列有一个 join() 方法,可简化按索引合并的过程。它还可用于合并具有相同或相似索引但没有重叠列的多个 DataFrame 对象。在前面的示例中,可以这样写: 

left2.join(right2, how="outer") 输出:

OhioNevadaMissouriAlabama
a12<NA><NA>
b<NA><NA>78
c34910
d<NA><NA>1112
e561314

与 pandas.merge 相比,DataFrame实列的 join() 方法默认对连接键执行左连接。它还支持将括号中传递的DataFrame实例的索引连接到调用join方法的 DataFrame 实例的其中一列上,相当于将join()括号中DataFrame实列的数据连接到调用了 join 方法的对象中:

left1.join(right1, on="key") 输出:

keyvaluegroup_val
0a03.5
1b17.0
2a23.5
3a33.5
4b47.0
5c5NaN

最后,索引与索引的合并,可以传递要合并的 DataFrames 对象列表给join()方法,作为下面要学习的 pandas.concat 函数的替代方法,例如:

import numpy as np
import pandas as pd# left2和right2的数据都是用pandas扩展类型Int64,允许空的整数
left2 = pd.DataFrame([[1., 2.], [3., 4.], [5., 6.]],index=["a", "c", "e"],columns=["Ohio", "Nevada"]).astype("Int64")
right2 = pd.DataFrame([[7., 8.], [9., 10.], [11., 12.], [13, 14]],index=["b", "c", "d", "e"],columns=["Missouri", "Alabama"]).astype("Int64")
another = pd.DataFrame([[7., 8.], [9., 10.], [11., 12.], [16., 17.]],index=["a", "c", "e", "f"],columns=["New York", "Oregon"])left2.join([right2, another])
left2.join([right2, another], how="outer")

left2.join([right2, another]) 输出:

OhioNevadaMissouriAlabamaNew YorkOregon
a12<NA><NA>7.08.0
c349109.010.0
e56131411.012.0

left2.join([right2, another], how="outer") 输出:

OhioNevadaMissouriAlabamaNew YorkOregon
a12<NA><NA>7.08.0
c349109.010.0
e56131411.012.0
b<NA><NA>78NaNNaN
d<NA><NA>1112NaNNaN
f<NA><NA><NA><NA>16.017.0

 三、沿轴(Axis)进行连接

另一种沿轴方向的数据组合操作方式可互相称为 concatenation 或 stacking。NumPy 的 concatenate 函数可以对 NumPy 数组执行此操作,看代码示例:

import numpy as np
import pandas as pdarr = np.arange(12).reshape((3, 4))
print(arr)
print(np.concatenate([arr, arr], axis=1))

 print(arr)输出:

[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]

print(np.concatenate([arr, arr], axis=1)) 输出:

[[ 0  1  2  3  0  1  2  3]
 [ 4  5  6  7  4  5  6  7]
 [ 8  9 10 11  8  9 10 11]]

在 pandas 对象(如 Series 和 DataFrame对象)的上下文中,具有标记的轴使我们能够进一步泛化数组连接。那么:

如果对象在其他轴上的索引方式不同,我们应该组合这些轴上的不同元素还是只使用共同的值?

是否需要在结果对象中识别串联的数据块?

“连接轴”是否包含需要保留的数据?

在许多情况下,DataFrame 中的默认整数标签在串联过程中丢弃

pandas 中的 concat 函数提供了一种方法来解决这些问题。下面通过代码示例来学习使用。

假设我们有三个没有索引重叠的 Series,

s1 = pd.Series([0, 1], index=["a", "b"], dtype="Int64")

s2 = pd.Series([2, 3, 4], index=["c", "d", "e"], dtype="Int64")

s3 = pd.Series([5, 6], index=["f", "g"], dtype="Int64")

pd.concat([s1, s2, s3]) 输出:

a    0
b    1
c    2
d    3
e    4
f    5
g    6
dtype: Int64

默认情况下,pandas.concat 沿 axis=“index” 工作,生成另一个 Series。如果传递 axis=“columns”,则结果将是一个 DataFrame对象。

pd.concat([s1, s2, s3], axis="columns") 输出:

012
a0<NA><NA>
b1<NA><NA>
c<NA>2<NA>
d<NA>3<NA>
e<NA>4<NA>
f<NA><NA>5
g<NA><NA>6

以上这种情况,由于另一个轴上没有重叠,这就相当于是索引的联合(“外”连接)。相反,我们可以通过传递参数 join=“inner” 来使它们相交:

import numpy as np
import pandas as pds1 = pd.Series([0, 1], index=["a", "b"], dtype="Int64")
s2 = pd.Series([2, 3, 4], index=["c", "d", "e"], dtype="Int64")
s3 = pd.Series([5, 6], index=["f", "g"], dtype="Int64")s4 = pd.concat([s1, s3])result = pd.concat([s1, s4], axis="columns")
result_inner = pd.concat([s1, s4], axis="columns", join="inner")
print(s4)
print(result)
print(result_inner)

s4输出:

a    0
b    1
f     5
g    6
dtype: Int64

result输出:

01
a00
b11
f<NA>5
g<NA>6

 result_inner输出:

01
a00
b11

从result_inner输出结果可以看出,由于使用了 join=“inner” ,“f” 和 “g” 标签行被丢弃了。

上面的示例发现了一个潜在的问题是,就是在结果中无法识别串联的片段,即无法在结果中识别出s1、s2、s3、s4等。为了能够识别,我们可以在串联轴上使用keys参数创建分层索引:

import numpy as np
import pandas as pds1 = pd.Series([0, 1], index=["a", "b"], dtype="Int64")
s2 = pd.Series([2, 3, 4], index=["c", "d", "e"], dtype="Int64")
s3 = pd.Series([5, 6], index=["f", "g"], dtype="Int64")result = pd.concat([s1, s1, s3], keys=["one", "two", "three"])
print(result)print(result.unstack())

result输出:

one    a    0
          b    1
two    a     0
          b    1
three  f     5
          g    6
dtype: Int64

 print(result.unstack()) 输出:

abfg
one01<NA><NA>
two01<NA><NA>
three<NA><NA>56

在沿 axis=“columns” 组合 Series 的情况下,键成为 组合生成的DataFrame 的列标题:

import numpy as np
import pandas as pds1 = pd.Series([0, 1], index=["a", "b"], dtype="Int64")
s2 = pd.Series([2, 3, 4], index=["c", "d", "e"], dtype="Int64")
s3 = pd.Series([5, 6], index=["f", "g"], dtype="Int64")result = pd.concat([s1, s2, s3], axis="columns", keys=["one", "two", "three"])
print(result)

 result输出:

onetwothree
a0<NA><NA>
b1<NA><NA>
c<NA>2<NA>
d<NA>3<NA>
e<NA>4<NA>
f<NA><NA>5
g<NA><NA>6

相同的逻辑衍生到 DataFrame 对象,看如下代码示例: 

import numpy as np
import pandas as pddf1 = pd.DataFrame(np.arange(6).reshape(3, 2), index=["a", "b", "c"],columns=["one", "two"])
df2 = pd.DataFrame(5 + np.arange(4).reshape(2, 2), index=["a", "c"],columns=["three", "four"])
print(df1)
print(df2)
result = pd.concat([df1, df2], axis="columns", keys=["level1", "level2"])
print(result)

 df1输出:

onetwo
a01
b23
c45

df2输出:

threefour
a56
c78

result输出(level1和level2作为了生成的DataFrame的列标签,这里是分层索引的第一级,并且能够通过这个标签识别出串联前的DataFrame对象):

level1level2
onetwothreefour
a015.06.0
b23NaNNaN
c457.08.0

 如果我们将对象字典传递给concat方法,则字典的key将作为keys参数的值,例如:

pd.concat({"level1": df1, "level2": df2}, axis="columns")

这行代码的输出与pd.concat([df1, df2], axis="columns", keys=["level1", "level2"])的输出相同。

下图中的列表是可以用于创建分层索引的其他参数控制。

例如,我们可以使用 names 参数命名创建的轴级别:

import numpy as np
import pandas as pddf1 = pd.DataFrame(np.arange(6).reshape(3, 2), index=["a", "b", "c"],columns=["one", "two"])
df2 = pd.DataFrame(5 + np.arange(4).reshape(2, 2), index=["a", "c"],columns=["three", "four"])result = pd.concat([df1, df2], axis="columns", keys=["level1", "level2"], names=["upper", "lower"])
print(result)

这里用names参数给生成的分层索引命名,外层是upper,内层是lower。上面示例代码输出:

upperlevel1level2
loweronetwothreefour
a015.06.0
b23NaNNaN
c457.08.0

最后一个注意事项,对于行索引不包含任何相关数据的 DataFrame,可以传递 ignore_index=True给concat()方法,这将丢弃每个 DataFrame 中的索引,仅连接列中的数据,并分配新的默认索引,例如:

import numpy as np
import pandas as pddf1 = pd.DataFrame(np.random.standard_normal((3, 4)),columns=["a", "b", "c", "d"])
df2 = pd.DataFrame(np.random.standard_normal((2, 3)),columns=["b", "d", "a"])result = pd.concat([df1, df2], ignore_index=True)
print(df1, "\n", df2, "\n", result)

 df1输出:

abcd
0-1.2659340.119827-1.0635120.332883
1-2.359419-0.199543-1.541996-0.970736
2-1.3070300.2863500.377984-0.753887

df2输出:

bda
00.3312861.3497420.069877
10.246674-0.0118621.004812

 result输出:

abcd
0-1.2659340.119827-1.0635120.332883
1-2.359419-0.199543-1.541996-0.970736
2-1.3070300.2863500.377984-0.753887
30.0698770.331286NaN1.349742
41.0048120.246674NaN-0.011862

 四、使用 Overlap 合并数据

 还有一种不能表示为合并或串联操作的数据组合情况,比如对两个索引完全或部分重叠的数据集进行合并,我们使用 NumPy 的 where 函数,它执行面向数组的与 if-else 表达式的等效的操作。例如:

import numpy as np
import pandas as pda = pd.Series([np.nan, 2.5, 0.0, 3.5, 4.5, np.nan],index=["f", "e", "d", "c", "b", "a"])
b = pd.Series([0., np.nan, 2., np.nan, np.nan, 5.],index=["a", "b", "c", "d", "e", "f"])
result = np.where(pd.isna(a), b, a)
print(a, "\n", b, "\n", result)

 a输出:

f    NaN
e    2.5
d    0.0
c    3.5
b    4.5
a    NaN
dtype: float64 

b输出:

a    0.0
b    NaN
c    2.0
d    NaN
e    NaN
f    5.0
dtype: float64

result输出:

[0.  2.5 0.  3.5 4.5 5. ]

np.where(pd.isna(a), b, a) 表示只要 a 中的值为 null,就会选择 b 中的值,否则选择 a 中的非 null 值。使用 numpy.where 不会检查索引标签是否对齐(甚至不要求对象具有相同的长度)。如果要按索引排列值,我们可以使用 Series combine_first 方法。

例如对于上面的Series对象a和b:a.combine_first(b) 输出:

a    0.0
b    4.5
c    3.5
d    0.0
e    2.5
f     5.0
dtype: float64

对于 DataFrames 对象,combine_first逐列执行相同的操作,我们可以将其视为用传递给combine_first的对象中的数据“修补”调用对象中的缺失数据:

import numpy as np
import pandas as pddf1 = pd.DataFrame({"a": [1., np.nan, 5., np.nan],"b": [np.nan, 2., np.nan, 6.],"c": range(2, 18, 4)})
df2 = pd.DataFrame({"a": [5., 4., np.nan, 3., 7.],"b": [np.nan, 3., 4., 6., 8.]})result = df1.combine_first(df2)
print(df1, "\n", df2, "\n", result)

df1输出:

abc
01.0NaN2
1NaN2.06
25.0NaN10
3NaN6.014

df2输出:

ab
05.0NaN
14.03.0
2NaN4.0
33.06.0
47.08.0

 df1.combine_first(df2)输出:

abc
01.0NaN2.0
14.02.06.0
25.04.010.0
33.06.014.0
47.08.0NaN

对于 DataFrame 对象的 combine_first() 方法调用的输出将具有所有列名的并集。


http://www.mrgr.cn/news/67400.html

相关文章:

  • 推荐一款强大的图像处理软件:Adobe Photoshop2025
  • 【网络安全】|nessus使用
  • Elasticsearch实战应用:构建高效的全文搜索引擎
  • Hive SQL中判断内容包含情况的全面指南
  • pinctrl语法
  • 三维测量与建模笔记 - 3.1 相机标定基本概念
  • 云数据中心基础环境-详细设计方案(364页WORD)
  • 什么是方法区(线程共享)?
  • 数据分析:16s扩增子网络分析之SparCC
  • Power Pivot、Power BI 和 SQL Server Analysis Services 的公式语言:DAX(数据分析表达式)
  • 【NOIP提高组】引水入城
  • GB/T 28046.4-2011 道路车辆 电气及电子设备的环境条件和试验 第4部分:气候负荷(2)
  • 个人测评之罗技G502X
  • 【算法】【优选算法】滑动窗口(下)
  • Linux系统I/O调优实例
  • Java+控制台 商城销售系统
  • C++开发基础之使用librabbitmq库实现RabbitMQ消息队列通信
  • MySQL:表的增删改查(进阶)
  • 修改云服务器远程默认端口
  • Docker学习: Docker介绍和安装以及常用命令
  • Stable Diffusion Web UI - ControlNet 景深 Depth
  • [数组排序] 0912. 排序数组
  • C++入门基础知识139—【关于C++ 类访问修饰符】
  • 「Mac畅玩鸿蒙与硬件32」UI互动应用篇9 - 番茄钟倒计时应用
  • C/C++」C++类型转换 之 dynamic_cast 操作符
  • 【Golang】validator库的使用