Python数据分析NumPy和pandas(十一、pandas的基本功能和使用)

一、重新索引

pandas 对象的一个重要方法是 reindex,使用reindex可以创建一个新对象,并且原对象的值与新索引对齐重新排列。

import pandas as pd

obj = pd.Series([4.5, 7.2, -5.3, 3.6], index=["d", "b", "a", "c"])
obj2 = obj.reindex(["a", "b", "c", "d", "e"])

print(obj)
print(obj2)

pandas对象调用 reindex方法,将根据新索引重新排列数据创建新对象,如果新索引与原索引无法对齐,则未对齐的索引引入缺失值。以上代码中,obj调用reindex方法中包含索引e,而原索引不包含e,因此新对象obj2的索引e引入缺失值NaN。

obj输出如下:

d    4.5
b    7.2
a   -5.3
c    3.6
dtype: float64

obj2输出如下:

a   -5.3
b    7.2
c    3.6
d    4.5
e    NaN
dtype: float64

在进行数据分析的时候,我们有时候会插入一些填充值。比如,对于像时间序列这样的有序数据,可能想在重新索引时做一些插值或填充值。reindex方法的method 参数允许我们使用 ffill 等方法来执行此操作,该方法正向填充值。

import pandas as pd

obj3 = pd.Series(["blue", "purple", "yellow"], index=[0, 2, 4])
print(obj3)
o = obj3.reindex(np.arange(6), method="ffill")
print(o)

输出:

0      blue
2    purple
4    yellow
dtype: object
0      blue
1      blue
2    purple
3    purple
4    yellow
5    yellow
dtype: object

在DataFrame中使用reindex可以更改 (行) 索引、列或者两者都可以更改。当仅传递一个序列给reindex时,它会重新索引结果中的行:

import numpy as np
import pandas as pd

#用numpy数组构造DataFrame对象
frame = pd.DataFrame(np.arange(9).reshape((3, 3)),
                     index=["a", "c", "d"],
                     columns=["Ohio", "Texas", "California"])
print(frame)

#重新索引frame,因为只传入了一个序列["a", "b", "c", "d"],所以重定义frame的行索引
frame2 = frame.reindex(index=["a", "b", "c", "d"])
print(frame2)

   Ohio  Texas  California
a     0      1           2
c     3      4           5
d     6      7           8

重新reindex后输出:

   Ohio  Texas  California
a   0.0    1.0         2.0
b   NaN    NaN    NaN
c   3.0    4.0         5.0
d   6.0    7.0         8.0

要改变DataFrame的列索引,可以在reindex中使用columns参数指定新索引序列。如下:

import numpy as np
import pandas as pd

#用numpy数组构造DataFrame对象
frame = pd.DataFrame(np.arange(9).reshape((3, 3)),
                     index=["a", "c", "d"],
                     columns=["Ohio", "Texas", "California"])
print(frame)

states = ["Texas", "Utah", "California"]
#在reindex方法中使用columns参数指定修改列索引序列
f = frame.reindex(columns=states)
print(f)

输出:

   Texas  Utah  California
a      1   NaN           2
c      4   NaN           5
d      7   NaN           8

上面代码中,由于“Ohio” 不在states序列中,因此将从结果中删除该列的数据,同事Utah列填充NaN值。重新索引特定轴的另一种方法是将新的轴标签作为位置参数传递,然后使用 axis 参数(关键字)指定要重新索引的轴:

例如将上面的代码改为 f = frame.reindex(states, axis="columns") 将输出同样的结果。

reindex方法的参数列表如下:

我们还可以使用 loc 运算符重新编制索引,许多人更喜欢这种方式进行重新索引。使用loc运算符时仅当 DataFrame 已存在所有新索引标签时,才有效(而 reindex 将为新标签插入缺失数据NaN)。例如:

f = frame.loc[["a", "d", "c"], ["California", "Texas"]]

输出:

   California  Texas
a           2      1
d           8      7
c           5      4

二、从Axis(轴)删除整个条目数据(可理解为按行或按列删除)

根据上面的学习,我们发现基于reindex方法和loc方法运算,也可以删除rows或columns。但更多的可以用drop方法来删除,该方法也返回一个新对象,不改变原对象。

import numpy as np
import pandas as pd

obj = pd.Series(np.arange(5.), index=["a", "b", "c", "d", "e"])
print(obj)

#删除obj中索引c指示的行
new_obj = obj.drop("c")
print(new_obj)

输出:

a    0.0
b    1.0
c    2.0
d    3.0
e    4.0
dtype: float64
a    0.0
b    1.0
d    3.0
e    4.0
dtype: float64

drop方法生成的新对象new_obj中删除了索引c指示的行。

可以在drop方法中传递序列删除多rows,例如:new_obj2 = obj.drop(["d", "c"]) 输出结果

a    0.0
b    1.0
e    4.0
dtype: float64

在DataFrame中,可以从任何一个Axis(轴)中删除索引值,直接代码演示(注意看代码中的注释说明)

import numpy as np
import pandas as pd

#用一个4x4的NumPy数组创建一个DataFrame对象,用index和columns指定行索引和列标签
data = pd.DataFrame(np.arange(16).reshape((4, 4)),
                    index=["Ohio", "Colorado", "Utah", "New York"],
                    columns=["one", "two", "three", "four"])

#打印data出来看下
print(data)

#删除指定的行索引的值
data1 = data.drop(index=["Colorado", "Ohio"])
print(data1)

#删除指定的列标签的值
data2 = data.drop(columns=["two"])
print(data2)

#通过指定轴号删除该轴方向的某个标签的值 例如列标签two。这种方式等价于data.drop(columns=['two'])
data3 = data.drop("two", axis=1)
print(data3)

#通过指定轴名称删除该方向指定列标签的值
data4 = data.drop(["two", "four"], axis="columns")
print(data4)

以上代码原对象data输出:

one two three four
Ohio 0 1 2 3
Colorado 4 5 6 7
Utah 8 9 10 11
New York 12 13 14 15

data1输出:

one two three four
Utah 8 9 10 11
New York 12 13 14 15

 data2输出:

one three four
Ohio 0 2 3
Colorado 4 6 7
Utah 8 10 11
New York 12 14 15

 data3输出(于data2相同结果):

one three four
Ohio 0 2 3
Colorado 4 6 7
Utah 8 10 11
New York 12 14 15

data4输出:

one three
Ohio 0 2
Colorado 4 6
Utah 8 10
New York 12 14

 三、从Series和DataFrame中索引、选择和筛选数据

还是用代码来学习会比较直观。

import numpy as np
import pandas as pd

#用numpy数组创建一个Series对象obj,并指定其索引
obj = pd.Series(np.arange(4.), index=["a", "b", "c", "d"])

#通过索引选择
print(obj["b"])

#通过index序号选择,这种方式一般不推荐使用,在新的版本中,整数键将始终被视为标签
print(obj[1])

#通过index序号片段选择
print(obj[2:4])

#通过index序列选择
print(obj[["b", "a", "d"]])

#通过index序号序列选择,不推荐使用整数
print(obj[[1, 3]])

#通过布尔运算选择,选择运算结果为True的值
print(obj[obj < 2])

以上代码输出:

1.0

1.0


c    2.0
d    3.0
dtype: float64


b    1.0
a    0.0
d    3.0
dtype: float64

b    1.0
d    3.0
dtype: float64


a    0.0
b    1.0
dtype: float64

虽然我们可以上面这种按标签选择数据的方式,但选择索引值的首选方法是使用特殊的 loc 运算符 。例如:

obj.loc[["b", "a", "d"]]  输出:

b    1.0
a    0.0
d    3.0
dtype: float64

推荐首选 loc 的原因是在使用 [] 进行索引时对整数的处理方式不同。如果索引包含整数,则基于 [] 的常规索引会将整数视为标签,因此行为因索引的数据类型而异。还是用代码举例比较直观,如下:

import numpy as np
import pandas as pd

#索引包含整数
obj1 = pd.Series([1, 2, 3], index=[2, 0, 1])
#索引不包含整数
obj2 = pd.Series([1, 2, 3], index=["a", "b", "c"])

print(obj1)
print(obj2)

print(obj1[[0, 1, 2]])
print(obj2[[0, 1, 2]])

以上obj1输出:

2    1
0    2
1    3

obj2输出:
dtype: int64
a    1
b    2
c    3
dtype: int64

obj1[[0, 1, 2]]输出:

0    2
1    3
2    1
dtype: int64

obj2[[0, 1, 2]]输出:

a    1
b    2
c    3
dtype: int64

在上面的obj2对象上如果使用obj2.loc[[0, 1, 2]]将会报错,因为obj2索引不包含整数。

由于 loc 运算符仅使用标签进行索引,因此还有一个 iloc 运算符,该运算符仅使用整数进行索引,无论索引是否包含整数,都可以一致地工作:

obj1.iloc[[0, 1, 2]] 输出:

2    1
0    2
1    3
dtype: int64

obj2.iloc[[0, 1, 2]] 输出:

a    1
b    2
c    3
dtype: int64

注意:我们也可以使用标签进行切片,但它的工作方式与普通的 Python 切片不同,因为终端节点是包容性的(包含切片首尾元素),例如:obj2.loc["b":"c"]   输出:

b    2
c    3
dtype: int64

还可以通过这种方式修改相应部分的值:obj2.loc["b":"c"] = 5 输出obj2:

a    1
b    5
c    5
dtype: int64


下次学习对 DataFrame 索引,对其索引可以检索出单个值、序列、一列或多列值。

猜你喜欢

转载自blog.csdn.net/FreedomLeo1/article/details/143111198