Python数据分析NumPy和pandas(九、pandas数据结构之DataFrame)

DataFrame 表示一个矩形数据表,包含一个有序的命名列集合,每个列可以是不同的值类型(数字、字符串、布尔值等)。DataFrame 同时具有行索引和列索引;它可以被认为是一个 Series 的字典,所有 Series 都共享同一个索引。

注意:虽然 DataFrame 在物理上是二维的,但我们可以使用分层索引以表格格式表示更高维的数据。

构造 DataFrame 的方法有很多种,最常见的一种是从等长列表或 NumPy 数组的字典中构造。

from pandas import Series, DataFrame

data = {"state": ["Ohio", "Ohio", "Ohio", "Nevada", "Nevada", "Nevada"],
        "year": [2000, 2001, 2002, 2001, 2002, 2003],
        "pop": [1.5, 1.7, 3.6, 2.4, 2.9, 3.2]}
frame = DataFrame(data)

print(frame)

输出:

         state  year   pop
0       Ohio  2000  1.5
1       Ohio  2001  1.7
2       Ohio  2002  3.6
3  Nevada  2001  2.4
4  Nevada  2002  2.9
5  Nevada  2003  3.2 

与 Series 一样,生成的 DataFrame 将自动分配索引,并且列根据 data 中键的顺序(取决于它们在字典中的插入顺序)放置。

如果我们使用的是 Jupyter 笔记本来运行上面的代码,则 pandas DataFrame 对象将显示为对浏览器更友好的 HTML 表。如下图。

对于大型 DataFrame,head 方法仅选择前五行,tail方法返回最后五行:

frame.head() 输出:

    state  year  pop
0    Ohio  2000  1.5
1    Ohio  2001  1.7
2    Ohio  2002  3.6
3  Nevada  2001  2.4
4  Nevada  2002  2.9

frame.tail() 输出:
    state  year  pop
1    Ohio  2001  1.7
2    Ohio  2002  3.6
3  Nevada  2001  2.4
4  Nevada  2002  2.9
5  Nevada  2003  3.2

在构造DataFrame时,如果需要重新指定列的顺序,可以指定columns参数:

from pandas import Series, DataFrame

data = {"state": ["Ohio", "Ohio", "Ohio", "Nevada", "Nevada", "Nevada"],
        "year": [2000, 2001, 2002, 2001, 2002, 2003],
        "pop": [1.5, 1.7, 3.6, 2.4, 2.9, 3.2]}
frame = DataFrame(data, columns=["year", "state", "pop"])

print(frame)

输出:

   year   state  pop
0  2000    Ohio  1.5
1  2001    Ohio  1.7
2  2002    Ohio  3.6
3  2001  Nevada  2.4
4  2002  Nevada  2.9
5  2003  Nevada  3.2

Jupyter notebook输出:

year state pop
0 2000 Ohio 1.5
1 2001 Ohio 1.7
2 2002 Ohio 3.6
3 2001 Nevada 2.4
4 2002 Nevada 2.9
5 2003 Nevada 3.2

如果传递的columns中包含data不存在的键,则该列数据值为NaN,例如:

from pandas import Series, DataFrame

data = {"state": ["Ohio", "Ohio", "Ohio", "Nevada", "Nevada", "Nevada"],
        "year": [2000, 2001, 2002, 2001, 2002, 2003],
        "pop": [1.5, 1.7, 3.6, 2.4, 2.9, 3.2]}
frame2 = DataFrame(data, columns=["year", "state", "pop", "debt"])

print(frame2)

 输出:

    year        state  pop debt
0  2000       Ohio  1.5  NaN
1  2001       Ohio  1.7  NaN
2  2002       Ohio  3.6  NaN
3  2001  Nevada  2.4  NaN
4  2002  Nevada  2.9  NaN
5  2003  Nevada  3.2  NaN

用columns属性查看列信息,frame2.columns 输出:

Index(['year', 'state', 'pop', 'debt'], dtype='object')

可以通过以下方法将DataFrame中的列作为Series检索出来,例如:

frame2['state']  或者 frame2.state  输出:

0      Ohio
1      Ohio
2      Ohio
3    Nevada
4    Nevada
5    Nevada
Name: state, dtype: object

使用 iloc 和 loc 属性按位置或名称检索行

上面的frame2中,通过frame2.loc[1] 或 frame2.iloc[2] 可以检索出第1行和第2行。

frame2.loc[1]输出:

year     2001
state    Ohio
pop       1.7
debt      NaN
Name: 1, dtype: object

frame2.iloc[2] 输出:

year     2002
state    Ohio
pop       3.6
debt      NaN
Name: 2, dtype: object

对于frame2中的“debt”无值列,我们可以这样给它赋值:frame2["debt"] = 16.5 赋值后frame2输出:

year state pop debt
0 2000 Ohio 1.5 16.5
1 2001 Ohio 1.7 16.5
2 2002 Ohio 3.6 16.5
3 2001 Nevada 2.4 16.5
4 2002 Nevada 2.9 16.5
5 2003 Nevada 3.2 16.5

我们还可以通过将与frame2的列等长的numpy数组赋值给debt列,如下:

frame2["debt"] = np.arange(6.)  赋值后frame2输出:

year state pop debt
0 2000 Ohio 1.5 0.0
1 2001 Ohio 1.7 1.0
2 2002 Ohio 3.6 2.0
3 2001 Nevada 2.4 3.0
4 2002 Nevada 2.9 4.0
5 2003 Nevada 3.2 5.0

将列表或数组分配给DataFrame的某列时,值的长度必须与 DataFrame 的长度匹配。如果我们分配一个 Series,它的标签将完全重新对齐到 DataFrame 的索引,并在任何不存在的索引值中插入缺失值: 

val = pd.Series([-1.2, -1.5, -1.7], index=["two", "four", "five"])

frame2["debt"] = val

frame2输出结果如下:

year state pop debt
0 2000 Ohio 1.5 NaN
1 2001 Ohio 1.7 NaN
2 2002 Ohio 3.6 NaN
3 2001 Nevada 2.4 NaN
4 2002 Nevada 2.9 NaN
5 2003 Nevada 3.2 NaN

以上将val赋值给debt列,由于val的索引无法跟frame2的索引匹配,所以debt列都赋值成缺失值。

对DataFrame 分配不存在的列将创建新列:frame2["eastern"] = frame2["state"] == "Ohio"

该语句先通过frame2["state"] == "Ohio" 判断state列中的各行的值是否为“Ohio”,如果是输出True,不是输出False,整体输出一个bool型数组,并将该数组赋值给frame2的"eastern"列,又由于在frame2中不存在"eastern"这列,所以会创建该列,执行完这行代码后frame输出如下:

year state pop debt eastern
0 2000 Ohio 1.5 NaN True
1 2001 Ohio 1.7 NaN True
2 2002 Ohio 3.6 NaN True
3 2001 Nevada 2.4 NaN False
4 2002 Nevada 2.9 NaN False
5 2003 Nevada 3.2 NaN False

注意:不能使用 frame2.eastern属性表示法创建新列。 

可以使用del函数删除某列,例如 del frame2["eastern"]

from pandas import Series, DataFrame

data = {"state": ["Ohio", "Ohio", "Ohio", "Nevada", "Nevada", "Nevada"],
        "year": [2000, 2001, 2002, 2001, 2002, 2003],
        "pop": [1.5, 1.7, 3.6, 2.4, 2.9, 3.2]}
frame2 = DataFrame(data, columns=["year", "state", "pop", 'debt'])
frame2["eastern"] = frame2["state"] == "Ohio"

del frame2["eastern"]
print(frame2)

删除eastern列后frame2输出:

    year        state  pop debt
0  2000       Ohio  1.5  NaN
1  2001       Ohio  1.7  NaN
2  2002       Ohio  3.6  NaN
3  2001  Nevada  2.4  NaN
4  2002  Nevada  2.9  NaN
5  2003  Nevada  3.2  NaN 

frame2.columns 输出:Index(['year', 'state', 'pop', 'debt'], dtype='object')

通过DataFrame的索引返回的列是基础数据的视图,而不是副本。因此,对 Series 的任何就地修改都将反映在DataFrame 中。可以使用 Series 的 copy 方法显式复制该列。

另一种常见的数据格式是嵌套字典。如果将嵌套字典传递给 DataFrame,pandas 会将外部字典键解释为列,将内部键解释为行索引。例如:

from pandas import Series, DataFrame
populations = {"Ohio": {2000: 1.5, 2001: 1.7, 2002: 3.6},
               "Nevada": {2001: 2.4, 2002: 2.9}}
frame3 = DataFrame(populations)
print(frame3)

输出:

           Ohio  Nevada
2000   1.5     NaN
2001   1.7     2.4
2002   3.6     2.9

可以使用类似于NumPy的符号T,进行行列转换:frame3.T

用Jupyter插件 输出:

2000 2001 2002
Ohio 1.5 1.7 3.6
Nevada NaN 2.4 2.9

请注意,如果列并非都具有相同的数据类型,则转置会丢弃列数据类型,因此转置后再转置回来可能会丢失以前的类型信息。在这种情况下,列将变为纯 Python 对象的数组。 

用嵌套字典构造DataFrame,内部词典中的键被组合起来,形成结果中的索引。但如果指定了显式索引,则不然,例如:

pd.DataFrame(populations, index=[2001, 2002, 2003]) 输出:

Ohio Nevada
2001 1.7 2.4
2002 3.6 2.9
2003 NaN NaN

 populations中不含2003的键,但我们用index参数指定的索引中包含2003,不包含2000,所以结果中不包含2000所对应的行,包含2003对应的行,但是值为NaN。

可以使用Series类型的字典来构造DataFrame,我们从上面frame3中截取数据形成Series类型,然后构造字典,最后用该字典创建一个DataFrame对象。如下:

from pandas import Series, DataFrame

populations = {"Ohio": {2000: 1.5, 2001: 1.7, 2002: 3.6},
               "Nevada": {2001: 2.4, 2002: 2.9}}
frame3 = pd.DataFrame(populations)
print(frame3)

#frame3["Ohio"][:-1]形成Series对象
#2000  1.5
#2001  1.7
#frame3["Nevada"][:2]形成Series对象
#2000  NaN
#2001  2.4
pdata = {"Ohio": frame3["Ohio"][:-1],
         "Nevada": frame3["Nevada"][:2]}

tpd = DataFrame(pdata)
print(tpd)

输出结果:

           Ohio  Nevada
2000   1.5     NaN
2001   1.7     2.4

以下列表是可以传递给DataFrame构造函数的内容:

如果 DataFrame 的索引和列设置了 name 属性,输出DataFrame对象也会显示这些属性:

frame3.index.name = "year"  #设置索引名为year

frame3.columns.name = "state"  #设置列名为state

frame3输出:

state Ohio Nevada
year
2000 1.5 NaN
2001 1.7 2.4
2002 3.6 2.9

与 Series 不同,DataFrame 没有 name 属性。DataFrame 的 to_numpy 方法将 DataFrame 中包含的数据作为二维 ndarray 返回。

 frame3.to_numpy()

输出:

[[1.5 nan]
 [1.7 2.4]
 [3.6 2.9]]

如果 DataFrame 的列是不同的数据类型,则将选择合适的返回数组的数据类型以容纳所有列,例如我们将上面的frame2转换成numpy数组:frame2.to_numpy() 输出

[[2000, 'Ohio', 1.5, nan, True],
 [2001, 'Ohio', 1.7, nan, True],
 [2002, 'Ohio', 3.6, nan, True],
 [2001, 'Nevada', 2.4, nan, False],
 [2002, 'Nevada', 2.9, nan, False],
 [2003, 'Nevada', 3.2, nan, False]], dtype=object

选择object数据类型,这样所有的列的类型都能包容进去。


先学到这,下次深入学习Series和DataFrame的索引对象

猜你喜欢

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