Pandas 中两个索引不同的 Dataframe 的运算问题
2017-10-03 22:21阅读:
转载
Pandas
最重要的一个功能是,它可以对不同索引的对象进行算术运算。在将对象相加时,结果的索引取索引对的并集。自动的数据对齐在不重叠的索引处引入空值,默认为
NaN。
In
[1]:
import pandas as
pd
In
[2]:
date1 =
pd.date_range('2012-3-1',
periods=1)
data1 =
{'A':
1, 'B':
2, 'C':
3} df1 =
pd.DataFrame(dat
a
=data1,
index=date1)
In
[3]:
df1
Out[3]:
In
[4]:
df1 + df1
Out[4]:
In
[5]:
df1 * df1
Out[5]:
In
[6]:
df1 - df1
Out[6]:
In
[7]:
df1 / df1
Out[7]:
如果两个对象的索引或者列不同,pandas 会自动进行数据对齐,不对齐的数据会默认用 NaN 填充。
In
[8]:
date2 =
pd.date_range('2012-4-1',
periods=1)
data2 =
{'A':
4, 'B':
5, 'C':
6} df2 =
pd.DataFrame(data=data2,
index=date2)
In
[9]:
df2
Out[9]:
In
[10]:
df1 + df2
Out[10]:
|
A |
B |
C |
| 2012-03-01 |
NaN |
NaN |
NaN |
| 2012-04-01 |
NaN |
NaN |
NaN |
这可能不是你希望的结果,你只是想将两个 dataframe 合并在一起,那么可以采用 dataframe 对象的 add()
方法来相加,并指定 fill_value 参数:
In
[11]:
df1.add(df2,
fill_value=0)
Out[11]:
|
A |
B |
C |
| 2012-03-01 |
1 |
2 |
3 |
| 2012-04-01 |
4 |
5 |
6 |
如果你仅仅只是需要拼接两个 dataframe,那么直接使用 append 方法即可
In
[12]:
df1.append(df2)
Out[12]:
|
A |
B |
C |
| 2012-03-01 |
1 |
2 |
3 |
| 2012-04-01 |
4 |
5 |
6 |
也许这也不是某些人想要的结果,他们希望两个 dataframe 对应的行相加,即使索引不同。这就违背了 pandas
数据对齐的特性,这也是 dataframe 行索引和列列索引存在的意义。所以 dataframe
原生不支持这样的运算,为什么是这样呢?想想如果让两个索引不同的 dataframe
的对应列相加,那么加完之后新的对象的索引该用谁的呢。当然,如果非要这么做也并不是不可,我们可以用一些迂回的办法:
In
[13]:
pd.DataFrame(df1.values
+
df2.values,
columns=df1.columns)
Out[13]:
- 2、改变其中一个 dataframe 的行索引,使两个 dataframe 的行索引相同:
In
[14]:
df2_bak =
df2.copy()
# 如果不希望改变原对象的索引就做一份拷贝
df2_bak.index =
df1.index
In
[15]:
df2_bak
Out[15]:
In
[16]:
df1 + df2_bak
Out[16]:
- 3、用 reset_index() 方法重置列索引, 该方法返回一个新的 dataframe:
In
[17]:
df1.reset_index()
Out[17]:
|
index |
A |
B |
C |
| 0 |
2012-03-01 |
1 |
2 |
3 |
In
[18]:
df2.reset_index()
Out[18]:
|
index |
A |
B |
C |
| 0 |
2012-04-01 |
4 |
5 |
6 |
直接 reset 时,我们发现原来的 index 默认被作为 dataframe 的一列,这可能不是我们想要的。我们可以给
reset_index() 方法传递一个参数
drop=True:
In
[19]:
df1.reset_index(drop=True)
Out[19]:
In
[20]:
df2.reset_index(drop=True)
Out[20]:
In
[21]:
df1.reset_index(drop=True)
+
df2.reset_index(drop=True)
Out[21]:
如果仅仅是列索引不同,也可以用同样的方法:
In
[22]:
data3 =
{'D':
7, 'E':
8, 'F':
9} df3 =
pd.DataFrame(data=data3,
index=date1)
In
[23]:
df3
Out[23]:
In
[24]:
df1 + df3
Out[24]:
|
A |
B |
C |
D |
E |
F |
| 2012-03-01 |
NaN |
NaN |
NaN |
NaN |
NaN |
NaN |
In
[25]:
pd.DataFrame(df1.values
+
df2.values,
columns=df3.columns)
Out[25]:
那么到底什么是数据对齐,就是两个 dataframe 的相应位置没有一一对应的数据。
In
[26]:
data4 =
{'D':
7, 'E':
8, 'F':
9, 'G':
10} df4 =
pd.DataFrame(data=data4,
index=date1)
In
[27]:
df4
Out[27]:
|
D |
E |
F |
G |
| 2012-03-01 |
7 |
8 |
9 |
10 |
In
[28]:
df3 + df4
Out[28]:
|
D |
E |
F |
G |
| 2012-03-01 |
14 |
16 |
18 |
NaN |
这里在相加时,df3 实际上是变成了下面的样子(也就是在没有数据的位置默认用 NaN 填充):
In
[29]:
df3 =
pd.DataFrame(data=data3,
index=date1,
columns=list('DEFG'))
In
[30]:
df3
Out[30]:
|
D |
E |
F |
G |
| 2012-03-01 |
7 |
8 |
9 |
NaN |
In
[31]:
df3
Out[31]:
|
D |
E |
F |
G |
| 2012-03-01 |
7 |
8 |
9 |
NaN |
之所两个 df3 + df4 的 ‘G’ 所以对应的值为 NaN, 是因为任何数与 NaN 做运算都等于 NaN。
In
[32]:
1 +
np.nan
Out[32]:
nan
可以用 fillna 方法来重置填充值:
In
[33]:
df3.fillna(0)
Out[33]:
|
D |
E |
F |
G |
| 2012-03-01 |
7 |
8 |
9 |
0 |
In
[34]:
df3.fillna(0)
+ df4
Out[34]:
|
D |
E |
F |
G |
| 2012-03-01 |
14 |
16 |
18 |
10 |
In
[35]:
df1
Out[35]:
In
[36]:
df1.reset_index(drop=True)
Out[36]:
In
[37]:
df1
Out[37]: