Pandas

Pandas是一个强大的分析结构化数据的工具集;它的使用基础是Numpy(提供高性能的矩阵运算);用于数据挖掘和数据分析,同时也提供数据清洗功能。

0. Pandas数据结构分析

数据结构分析

0.1 Series

Series是一个类似一维数组的对象,他能够保存任何类型的数据,由左面的索引和右面的数据两部分组成。

0.1.1 语法:
pandas.Series(data=None, index=None, dtype=None, name=None, copy=False, fastpath=False)

部分参数:

  • data:数据
  • index:索引
0.1.2 使用:

代码:

import pandas as pd
# 创建Series对象
data = pd.Series(data=[2, 3, 4, 5])
print("data为:\n", data)
# 更改索引
data.index = [1, 2, 3, 4]
print("\n更改索引后的data为:\n", data)
# 由字典创建
info = {"name": "zz", "class": 'ji3'}
data = pd.Series(data=info)
print("\n由数据创建的data为:\n", data)
# 字符串索引
print("\ndata[1]=", data[1])
# 字符串拼接
print("\n字符串后加ha:\n", data + "ha")

输出:

data为:
 0    2
1    3
2    4
3    5
dtype: int64

更改索引后的data为:
 1    2
2    3
3    4
4    5
dtype: int64

由数据创建的data为:
 name      zz
class    ji3
dtype: object

data[1]= ji3

字符串后加ha:
 name      zzha
class    ji3ha
dtype: object

0.2 DataFrame

DataFrame是一个类似于二维数组或表格,他每列的数据可以是不同的数据类型。

0.2.1 语法
pandas.DataFrame(data=None, index=None, columns=None, dtype=None, copy=False)

部分参数说明:

  • index:表示行标签,若不设置参数则默认自动创建一个从0~N的整数索引
  • columns:列标签
0.2.2 使用:

代码:

import pandas as pd
# 创建DataFrame
df = pd.DataFrame([[56, 68, 11, 55], [57, 68, 11, 33], [57, 65, 11, 33]])
print("df=\n", df)
# 创建带行索引的DataFrame
df = pd.DataFrame([[56, 68, 11, 55], [57, 68, 11, 33], [57, 65, 11, 33]],
                  index=["zz", "wcc", "wyf"])
print("\ndf(带行索引)=\n", df)
# 创建带行列索引的DataFrame
df = pd.DataFrame([[56, 68, 11, 55], [57, 68, 11, 33], [57, 65, 11, 33]],
                  index=["zz", "wcc", "wyf"],
                  columns=["语文", "数学", "英语", "物理"])
print("\ndf(带行列索引)=\n", df)
# 添加数据
df["物理"] = [12, 22, 32]
print("\ndf(添加列)=\n", df)
# 删除列
del df["语文"]
print("\ndf(删除列)=\n", df)

输出:

df=
     0   1   2   3
0  56  68  11  55
1  57  68  11  33
2  57  65  11  33

df(带行索引)=
       0   1   2   3
zz   56  68  11  55
wcc  57  68  11  33
wyf  57  65  11  33

df(带行列索引)=
      语文  数学  英语  物理
zz   56  68  11  55
wcc  57  68  11  33
wyf  57  65  11  33

df(添加列)=
      语文  数学  英语  物理
zz   56  68  11  12
wcc  57  68  11  22
wyf  57  65  11  32

df(删除列)=
      数学  英语  物理
zz   68  11  12
wcc  68  11  22
wyf  65  11  32

1. Pandas索引操作及高级索引

1.1 对象索引

索引对象无法进行单独修改,保证数据安全,但是可以整体设置,例如:

import pandas as pd
data = pd.DataFrame([[66, 77, 98, 121], [75, 32, 111, 32], [11, 33, 23, 56]],
                    index=['wcc', 'wyf', 'yxy'],
                    columns=['跳高', '跳远', '竞走', '跑圈'])
print(data)
# data.index[1] = 'zz'  # 错误使用
data.index = ['zz', 'wyf', 'yxy']
print("修改后:", data)

如果输入代码第6行代码会报错:

TypeError: Index(...) must be called with a collection of some kind, 'zz' was passed

正确的代码输出为:

     跳高  跳远   竞走   跑圈
wcc  66  77   98  121
wyf  75  32  111   32
yxy  11  33   23   56
修改后:      跳高  跳远   竞走   跑圈
zz   66  77   98  121
wyf  75  32  111   32
yxy  11  33   23   56

✅扩展层次化索引

分层/多级索引在处理复杂的数据分析和数据操作方面为开发者奠定了基础,尤其是在处理高纬度数据处理上。本质上,它使您能够在较低维度的数据结构(如 Series(一维)和DataFrame (二维))中存储和操作任意维数的数据。

下面这个例子将演示如何由DataFrame对象创建层次化索引:

import pandas as pd
data = pd.DataFrame({
    "Country": ["Us", "China", "China", "China"],
    "Province": ["Washington", "Shandong", "Beijing", "Tianjin"],
    "People": ["zz", "bill", "wcc", "wyf"]
})
print(data.set_index(["Country", "Province"]))

输出为:

                   People
Country Province
Us      Washington     zz
China   Shandong     bill
        Beijing       wcc
        Tianjin       wyf

1.2 重置索引

Pandas中提供了一个重要方法reindex(),该方法的作用是对原索引和新索引进行匹配,也就是说,新索引含有原索引的数据,而原索引数据按照新索引排序。如果新索引中没有原索引数据,那么程序不仅不会报错而且会添加新索引并将值填充为NaN或者使用fill_values()填充其他值。

1.2.1 reindex()方法
reindex

语法:

DataFrame.reindex(labels=None,index=None,columns=None,axis=None,method=None,copy=True,level=None,fill_value=nan,limit=None,tolerance=None)

部分参数解释:

  • index:用作索引的新序列
  • method:插值填充方式
  • fill_value:引入缺失值时使用的替代值
  • limit:前向或后向填充时的最大填充量

前向/后向填充可以使用reindex()方法中的methon='ffill'(后向填充)、mothon='bfill'(前向填充),也可以使用ffill()bfill()方法,建议使用reindex().ffill()/reindex().bfill()


代码:

import pandas as pd
data = pd.Series([1,5,3,8,4], index=['b', 'e', 'a', 'd', 'g'])
print(data.reindex(['a', 'b', 'c', 'd', 'e', 'f', 'g'],
                   fill_value=6))  # 填充缺失值为6
print(data.reindex(['a', 'b', 'c', 'd', 'e', 'f', 'g']).bfill())  # 后向填充
print(data.reindex(['a', 'b', 'c', 'd', 'e', 'f', 'g']).ffill())  # 前向填充

输出:

a    3
b    1
c    6
d    8
e    5
f    6
g    4
dtype: int64
a    3.0
b    1.0
c    8.0
d    8.0
e    5.0
f    4.0
g    4.0
dtype: float64
a    3.0
b    1.0
c    1.0
d    8.0
e    5.0
f    5.0
g    4.0
dtype: float64

1.3 索引操作

1.3.1 Series索引
基础索引

Series有关索引与Numpy相似,对于Series索引既可通过位置也可通过index(索引名称)获取:

import pandas as pd
data = pd.Series(range(1, 6), index=['a', 'b', 'c', 'd', 'e'])
print("位于2位置的元素为:", data[2])
print("索引名称为'c'的元素为:", data['c'])

输出为:

位于2位置的元素为: 3
索引名称为'c'的元素为: 3
索引

Series切片索引

总结:
由于Series的索引有两种形式,因此切片也有两种形式但是有一点点区别:

  • 位置索引:包括起始位置不包括终止位置
  • 名称索引:包括起始位置和终止位置

位置索引:
语法:

pandas[start:stop:step]

代码:

import pandas as pd
dataSlice = pd.Series(range(1, 10),
                      index=['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'])

# 位置索引的几种形式
print("位置在[2,6)之间的元素为:")
print(dataSlice[2:6])
print("位置在[6,2)之间的元素(逆序)为:")
print(dataSlice[6:2:-1])
print("位置在[6,2)之间(步长为2)的元素(逆序)为:")
print(dataSlice[6:2:-2])

输出:

位置在[2,6)之间的元素为:
c    3
d    4
e    5
f    6
dtype: int64
位置在[6,2)之间的元素(逆序)为:
g    7
f    6
e    5
d    4
dtype: int64
位置在[6,2)之间(步长为2)的元素(逆序)为:
g    7
e    5
dtype: int64

名称索引:
语法:

pandas[start:stop:step]

代码:

import pandas as pd
dataSlice = pd.Series(range(1, 10),
                      index=['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'])
print("名称在[c,g]之间的元素为:")
print(dataSlice['c':'g'])
print("名称在[g,c]之间的元素(逆序)为:")
print(dataSlice['g':'c':-1])
print("名称在[c,g]之间(步长为2)的元素(逆序)为:")
print(dataSlice['g':'c':-2])

输出:

名称在[c,g]之间的元素为:
c    3
d    4
e    5
f    6
g    7
dtype: int64
名称在[g,c]之间的元素(逆序)为:
g    7
f    6
e    5
d    4
c    3
dtype: int64
名称在[c,g]之间(步长为2)的元素(逆序)为:
g    7
e    5
c    3
dtype: int64

不连续索引

代码:

import pandas as pd
dataSlice = pd.Series(range(1, 10),
                      index=['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'])
print(dataSlice[[1, 2, 5]])
print(dataSlice[['a', 'd', 'e']])

输出:

b    2
c    3
f    6
dtype: int64
a    1
d    4
e    5
dtype: int64

布尔型索引

返回符合表达式的变量。

代码:

import pandas as pd
dataSlice = pd.Series(range(1, 10),
                      index=['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'])
print(dataSlice[dataSlice > 6])

输出:

g    7
h    8
i    9
dtype: int64
1.3.2 DataFrame索引
基础索引
DataFrame索引

语法:

DataFrame[index][column]

✅ 基础语法只能为先行后列,index仅可使用切片,column可以为切片或元素,因此当DataFrame索引只有一个对象时使用名称索引会直接匹配列即column参数。

代码:

import numpy as np
import pandas as pd
data = pd.DataFrame(np.arange(12).reshape(3, 4), columns=['a', 'b', 'c', 'd'])
# 两参数索引
print("两参数索引:")
print(data[1:2]['a'])
# 不连续Series对象索引
print("不连续Series对象索引:")
print(data[['a', 'c']])
# 使用切片进行行索引
print("使用切片进行行索引:")
print(data[:2])
# 获取b列的数据
print("b列的数据:")
print(data['b'])
# 行列序号相同时的单参数名称索引
print("行列序号相同时的单参数名称索引:")
data_2 = pd.DataFrame(np.arange(12).reshape(3, 4))
print("行号:", data_2.index)
print("列号:", data_2.columns)
print(data_2[2])

输出:

两参数索引:
1    4
Name: a, dtype: int32
不连续Series对象索引:
   a   c
0  0   2
1  4   6
2  8  10
使用切片进行行索引:
   a  b  c  d
0  0  1  2  3
1  4  5  6  7
b列的数据:
0    1
1    5
2    9
Name: b, dtype: int32
行列序号相同时的单参数名称索引:
行号: RangeIndex(start=0, stop=3, step=1)
列号: RangeIndex(start=0, stop=4, step=1)
0     2
1     6
2    10
Name: 2, dtype: int32
高级索引

**

Pandas库中提供了操作索引的方法来访问数据,具体包括:

  • loc:基于标签索引(索引名称,如a、b等),用于按标签选取数据,当执行切片操作时既包含起始索引也包括结束索引。
  • iloc:基于位置索引(整数索引,从0到length-1),用于按位置选取数据。当执行切片操作时,只包含起始索引不包括结束索引。

ilog主要使用整数来索引数据而不能使用字符标签来索引数据,而loc只能使用字符标签来索引数据而不能使用整数来索引数据。

DataFrame高级索引

loc
代码:

import numpy as np
import pandas as pd
data = pd.DataFrame(np.arange(16).reshape(4, 4), columns=['a', 'b', 'c', 'd'])
print(data.loc[:, ['a', 'c']])

输出:

    a   c
0   0   2
1   4   6
2   8  10
3  12  14

iloc
代码:

import numpy as np
import pandas as pd
data = pd.DataFrame(np.arange(16).reshape(4, 4), columns=['a', 'b', 'c', 'd'])
print(data.iloc[:, [2, 0]])

输出:

    c   a
0   2   0
1   6   4
2  10   8
3  14  12

lociloc函数第一个参数是行索引,例如:

import numpy as np
import pandas as pd
data = pd.DataFrame(np.arange(16).reshape(4, 4), columns=['a', 'b', 'c', 'd'])
print(data.iloc[1:3, [2, 0]])

输出为:

   c  a
1   6  4
2  10  8

2. 算术运算与数据对齐

Series的算术运算

在Pandas中Series对象进行运算时,索引长度不同的Series对象进行运算缺失值处会填充为NaN,如果希望使用NaN填充缺失数据可以使用方法中的fill_value参数,例子以加法为例:

import pandas as pd
data = pd.Series([1, 4, 5])
data_2 = pd.Series([0, 7, 6, 8, 4])
print(data.add(data_2, fill_value=0))

输出为:

0     1.0
1    11.0
2    11.0
3     8.0
4     4.0
dtype: float64

即:

填充缺失值

3. 数据排序

3.1 按索引排序

3.1.1 语法
sort_index(axis=0,level=None,ascending=True,inplace=False,kind='quicksort',na_position='last',sort_remaining=True)

部分参数说明:

  • axis:轴索引,0表示index(行),1表示columns(列)
  • level:若不为None,则对指定索引级别的值进行排序
  • ascending:是否升序排序,默认True表示升序
  • inplace:默认为False表示对数据表进行排序不创建新实例
  • kind:选择排序算法
3.1.2 Series对象
直接排序

代码:

import pandas as pd
data = pd.Series(range(6),index=[1,5,7,6,3,2])
print(data.sort_index())

输出:

1    0
2    5
3    4
5    1
6    3
7    2
dtype: int64
降序排序

代码:

import pandas as pd
data = pd.Series(range(6),index=[1,5,7,6,3,2])
print(data.sort_index(ascending=False))

输出:

7    2
6    3
5    1
3    4
2    5
1    0
dtype: int64
3.1.3 DataFrame对象
按行索引升序排序

代码:

import numpy as np
import pandas as pd
data = pd.DataFrame(np.arange(12).reshape(3,4),index=[5,1,2],columns=[8,2,1,3])
print(data.sort_index())

输出:

   8  2   1   3
1  4  5   6   7
2  8  9  10  11
5  0  1   2   3
按列索引降序排序

代码:

import numpy as np
import pandas as pd
data = pd.DataFrame(np.arange(12).reshape(3, 4),
                    index=[5, 1, 2],
                    columns=[8, 2, 1, 3])
print(data.sort_index(axis=1, ascending=False))

输出:

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

3.2 按值排序

3.2.1 语法
sort_values(by,axis=0,level=None,ascending=True,inplace=False,kind='quicksort',na_position='last')

部分参数说明:

  • by:排序的列
  • axis:轴索引,0表示index(行),1表示columns(列)
  • level:若不为None,则对指定索引级别的值进行排序
  • ascending:是否升序排序,默认True表示升序
  • na_position:如果设置为first则会将NaN值放在开头;如果设置为last则会将NaN值放在最后。
3.2.2 Series对象
升序排序

代码:

import numpy as np
import pandas as pd
data = pd.Series([4, np.nan, 6, np.nan, -2, 2])
print(data.sort_values())

输出:

4   -2.0
5    2.0
0    4.0
2    6.0
1    NaN
3    NaN
dtype: float64
3.2.3 DataFrame对象
列索引排序

代码:

import pandas as pd
data = pd.DataFrame([[1, 2, 5, 4], [2, 5, 9, 1], [1, 5, 9, 11], [2, 8, 1, 2]])
print(data.sort_values(by=2))

输出:

   0  1  2   3
3  2  8  1   2
0  1  2  5   4
1  2  5  9   1
2  1  5  9  11

4. 统计计算与描述

4.1 常用的统计计算

函数名称 说明 函数名称 说明
sum std 标准差
mean 平均值 skew 三阶矩
median 中位数 kurt 四阶矩
max 最大值 min 最小值
idxmax 最大索引值 idxmin 最小索引值
count NaN值的个数 head 获取前N个值
var 方差 cumsum 累积和
cummin 累积最小值 cummax 累积最大值
cumprod 累计积 describe 列计算汇总
示例代码
import numpy as np
import pandas as pd
data = pd.DataFrame(np.arange(12).reshape(3,4),columns=['a','b','c','d'])
print("原数据:")
print(data)
print("求和:")
print(data.sum(axis=1))
print("求中位数:")
print(data.median())

输出:

原数据:
   a  b   c   d
0  0  1   2   3
1  4  5   6   7
2  8  9  10  11
求和:
0     6
1    22
2    38
dtype: int64
求中位数:
a    4.0
b    5.0
c    6.0
d    7.0
dtype: float64

4.2 describe统计描述

4.2.1 函数语法
describe(percentiles=None,include=None,exclude=None)

常用参数含义

  • percentiles:输出中包含的百分数,位于[0,1]之间,如果不设置参数则默认为[0.25,0.5,0.75],返回25%,50%,75%分位数。
  • includeexclude:指定返回结果的形式
4.2.2 示例代码
import numpy as np
import pandas as pd
data = pd.DataFrame(np.arange(12).reshape(3,4),columns=['a','b','c','d'])
print(data.describe())

输出:

         a    b     c     d
count  3.0  3.0   3.0   3.0
mean   4.0  5.0   6.0   7.0
std    4.0  4.0   4.0   4.0
min    0.0  1.0   2.0   3.0
25%    2.0  3.0   4.0   5.0
50%    4.0  5.0   6.0   7.0

参照数组:

   a  b   c   d
0  0  1   2   3
1  4  5   6   7
2  8  9  10  11

5.层次化索引

5.1 认识层次化索引

在一个轴方向上有多层索引。如图:

多级菜单

Series和DataFrame均可以实现层次化索引,最常见的方式是在构造方法的index参数中传入一个嵌套列表。

5.1.1 Series对象层次化索引

例如:

import pandas as pd
mulitindex_series = pd.Series(
    [12462, 1546, 1234, 123, 5456, 5554, 33213, 2124],
    index=[['河北省', '河北省', '河北省', '河北省', '河南省', '河南省', '河南省', '河南省'],
           ['石家庄市', '唐山市', '邯郸市', '秦皇岛市', '郑州市', '开封市', '洛阳市', '新乡市']])
print(mulitindex_series)

输出为:

河北省  石家庄市    12462
     唐山市      1546
     邯郸市      1234
     秦皇岛市      123
河南省  郑州市      5456
     开封市      5554
     洛阳市     33213
     新乡市      2124
dtype: int64
5.1.2 DataFrame对象层次化索引

例如:

import pandas as pd
mulitindex_DataFrame = pd.DataFrame(
    {'占地面积': [12462, 1546, 1234, 123, 5456, 5554, 33213, 2124]},
    index=[['河北省', '河北省', '河北省', '河北省', '河南省', '河南省', '河南省', '河南省'],
           ['石家庄市', '唐山市', '邯郸市', '秦皇岛市', '郑州市', '开封市', '洛阳市', '新乡市']])
print(mulitindex_DataFrame)

输出:

           占地面积
河北省 石家庄市  12462
    唐山市    1546
    邯郸市    1234
    秦皇岛市    123
河南省 郑州市    5456
    开封市    5554
    洛阳市   33213
    新乡市    2124

5.2 常用方法

总述:
层次化索引除了直接创建之外还可以通过MultiIndex类的方法构建层次化索引,这个类提供了三种创建层次化索引的方法:

  • MultiIndex.from_tuples():将元组列表转换为MultiIndex
  • MultiIndex.from_arrays():将数组列表转换为MultiIndex
  • MultiIndex.from_product():从多个集合的笛卡尔乘积中创建MultiIndex

from_tuples()
from_tuples()方法可以将包含若干个元组的列表转换为MultiIndex对象,其中元组的第一个元素作为外层索引,第二个元素作为内层索引,例如:

import pandas as pd
from pandas import MultiIndex
list_tuples = [('A', 'A1'), ('A', 'A2'), ('B', 'B1'), ('B', 'B2'), ('B', 'B3')]
multi_index = MultiIndex.from_tuples(tuples=list_tuples,
                                      names=['外层索引', '内层索引'])
value = [[1,2,3],[4,5,6],[7,8,9],[10,11,12],[13,14,15]]
df_indexs = pd.DataFrame(data=value,index=multi_index)
print(df_indexs)

输出为:

            0   1   2
外层索引 内层索引
A    A1     1   2   3
     A2     4   5   6
B    B1     7   8   9
     B2    10  11  12
     B3    13  14  15

from_arrays()
from_arrays()方法是将数组列表转换为MultiIndex对象,其中嵌套的第一个列表将作为外层索引,嵌套的第二个列表将作为内层索引。例如:

import pandas as pd
from pandas import MultiIndex
multi_array = MultiIndex.from_arrays(
    arrays=[['A', 'A', 'B', 'B', 'B'], ['A1', 'A2', 'B1', 'B2', 'B3']])
value = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12], [13, 14, 15]]
df_indexs = pd.DataFrame(data=value, index=multi_array)
print(df_indexs)

输出:

       0   1   2
A A1   1   2   3
  A2   4   5   6
B B1   7   8   9
  B2  10  11  12
  B3  13  14  15

from_product()
from_product()方法表示从多个集合的笛卡尔乘积创建一个MultiIndex对象。


什么是笛卡尔乘积?
笛卡尔积的符号化为:
A×B={(x,y)|x∈A∧y∈B}
例如,A={a,b}, B={0,1,2},则
A×B={(a, 0), (a, 1), (a, 2), (b, 0), (b, 1), (b, 2)}
B×A={(0, a), (0, b), (1, a), (1, b), (2, a), (2, b)}


例如:

import numpy as np
import pandas as pd
from pandas import MultiIndex
numbers = [0, 1, 2]
colors = ['green', 'purple']
multi_product = MultiIndex.from_product(iterables=[numbers, colors],
                                        names=['number', 'color'])
value = np.array([[7, 5], [6, 6], [3, 1], [5, 5], [4, 5], [5, 3]])
df_product = pd.DataFrame(data=value, index=multi_product)
print(df_product)

输出为:

               0  1
number color
0      green   7  5
       purple  6  6
1      green   3  1
       purple  5  5
2      green   4  5
       purple  5  3

5.3 层次化索引操作

任务一:录入下面层次化对象
层次化对象

代码:

import pandas as pd
ser_obj = pd.Series([78, 65, 44, 98, 66, 100, 97, 68],
                    index=[['机械', '机械', '机械', '信息', '信息', '工程', '工程', '工程'],
                           ['张三', '李四', '王二', '宋天', '汪全', '寒月', '天使', '葛藤']])

输出:

机械  张三     78
    李四     65
    王二     44
信息  宋天     98
    汪全     66
工程  寒月    100
    天使     97
    葛藤     68
dtype: int64
任务二:筛选外层索引为机械的数据

代码:

print(ser_obj['机械'])

输出:

张三    78
李四    65
王二    44
dtype: int64
任务三:筛选内层索引为李四的数据

代码:

print(ser_obj[:, '李四'])

输出:

机械    65
dtype: int64
任务四:交换分层顺序

代码:

print(ser_obj.swaplevel())

输出:

张三  机械     78
李四  机械     65
王二  机械     44
宋天  信息     98
汪全  信息     66
寒月  工程    100
天使  工程     97
葛藤  工程     68
dtype: int64
任务五:索引排序

sort_index()语法

sort_index(axis=0,level=None,ascending=True,inplace=False,kind='quicksort',na_position='last',sort_remaining=True,by=None)
  • by:表示按指定的值排序
  • ascending:布尔值,表示是否升序排列,默认为True

代码:

print(ser_obj.sort_index())

输出:

信息  宋天     98
    汪全     66
工程  天使     97
    寒月    100
    葛藤     68
机械  张三     78
    李四     65
    王二     44
dtype: int64

层次化索引中先对外层索引进行排序再对每一个外层索引的内层索引进行排序。如果需要对值进行排序可以使用sort_values()函数。


任务六:录入下面的层次化对象并对num列进行降序排序
层次化索引

代码:

import pandas as pd
dat_obj = pd.DataFrame(
    {
        "model": [
            'CPU', 'GPU', 'FLASH', 'SSD', 'HDD', 'USB', 'TYPE-C', 'MIC-USB',
            'DRIVE'
        ],
        "num": [80, 152, 113, 354, 1, 231, 35, 12, 7]
    },
    index=[['A', 'A', 'A', 'B', 'B', 'C', 'C', 'C', 'C'],
           [1, 2, 4, 3, 5, 1, 5, 8, 1]])
print(dat_obj.sort_values(by='num', ascending=False))

输出:

       model  num
B 3      SSD  354
C 1      USB  231
A 2      GPU  152
  4    FLASH  113
  1      CPU   80
C 5   TYPE-C   35
  8  MIC-USB   12
  1    DRIVE    7
B 5      HDD    1

6. 数据的读写

6.1 读写文本文件

6.1.1 写入文本文件函数to_csv()
函数语法:

详细参数请查看官方文档:DataFrame.to_csv()

to_csv(path_or_buf=None,sep=',',na_rep='',float_format=None,columns=None,header=True,index=True,index_label=None,mode='w',……)
  • path_or_buf:文件路径
  • index:默认为True,若设为False,则将不会显示索引
  • sep:分隔符,默认用","隔开
代码:
import pandas as pd
data_csv = pd.DataFrame(
    {
        "model": [
            'CPU', 'GPU', 'FLASH', 'SSD', 'HDD', 'USB', 'TYPE-C', 'MIC-USB',
            'DRIVE'
        ],
        "num": [80, 152, 113, 354, 1, 231, 35, 12, 7]
    },
    index=[['A', 'A', 'A', 'B', 'B', 'C', 'C', 'C', 'C'],
           [1, 2, 4, 3, 5, 1, 5, 8, 1]])
data_csv.to_csv('./test.csv', index=True)

这种方法同样可以输出扩展名为txt的文件。

输出:

在本目录会生成一个text.csv的文件,文件内容为:

,,model,num
A,1,CPU,80
A,2,GPU,152
A,4,FLASH,113
B,3,SSD,354
B,5,HDD,1
C,1,USB,231
C,5,TYPE-C,35
C,8,MIC-USB,12
C,1,DRIVE,7
6.1.2 读取文本文件函数read_csv()
函数语法:

详细参数请查看官方文档:Pandas.read_csv()

Pandas.read_csv(filepath_or_buffer,sep=',',delimiter=None,header='infer',names=None,index_col=None,usecols=None,prefix=None,……)
  • sep:指定使用的分隔符,默认用","分隔
  • header:指定行数用来作为列名
  • names:用于结果的列名列表,如果文件不包含标题行,则应该将参数设置为None

读取Text文件函数read_table()read_csv()相似,只不过read_table()函数默认使用"\t"为分隔符。

代码:

读取上文中生成的test.csv文件

import pandas as pd
data = pd.read_csv('./test.csv')
print(data)
输出:
  Unnamed: 0  Unnamed: 1    model  num
0          A           1      CPU   80      
1          A           2      GPU  152      
2          A           4    FLASH  113      
3          B           3      SSD  354      
4          B           5      HDD    1      
5          C           1      USB  231      
6          C           5   TYPE-C   35      
7          C           8  MIC-USB   12      
8          C           1    DRIVE    7

可以通过del data['Unnamed: 0']来删除该列。

6.2 读写EXCLE文件

Excle文件是常见的存储数据文件,它里面均是以二维表格的形式显示的,可以对数据进行统计分析等操作,常见扩展名为.xls.xlsx两种格式,对于Excle文件的读写常用的两个方法为to_excle()read_excle()两种方法。

6.2.2 写入Excle文件to_excle()方法
函数语法:

详细参数请查看官方文档:DataFrame.to_excel()

DataFrame.to_excel(excle_writer,sheet_name='Sheet1',na_rep='',float_format=None,columns=None,header=True,index=True,……)
  • excle_writer:表示读取的文件路径
  • sheet_name:表示工作表名称,默认为Sheet1
  • na_rep:表示缺失数据
  • index:表示是否写行索引,默认为True
代码:

读取上文中生成的test.csv文件

import pandas as pd
data_excle = pd.DataFrame(
    {
        "model": [
            'CPU', 'GPU', 'FLASH', 'SSD', 'HDD', 'USB', 'TYPE-C', 'MIC-USB',
            'DRIVE'
        ],
        "num": [80, 152, 113, 354, 1, 231, 35, 12, 7]
    },
    index=[['A', 'A', 'A', 'B', 'B', 'C', 'C', 'C', 'C'],
           [1, 2, 4, 3, 5, 1, 5, 8, 1]])
data_excle.to_excel('./test.xlsx', 'TestExcle')
输出:

将在根目录输出文件名为test.xlsx的表格,表格内容如图。

to_excle
6.2.2 读取Excle文件read_excle()方法
函数语法:

详细参数请查看官方文档:Pandas.read_excel()

Pandas.read_excle(io,sheet_name=0,header=0,name=None,index_col=None,**kwds)
  • io:表示路径对象
  • sheet_name:指定要读取的工作表,默认为0
  • header:用于解析DataFrame的列标签
  • names要使用的列名称
代码:

读取上文中生成的test.xlsx文件,由于Excle中合并的单元格会产生缺失值,使用ffill()方法进行向下填充。

import pandas as pd
data = pd.read_excel('./test.xlsx').ffill()
print(data)
输出:
  Unnamed: 0  Unnamed: 1    model  num
0          A           1      CPU   80
1          A           2      GPU  152
2          A           4    FLASH  113
3          B           3      SSD  354
4          B           5      HDD    1
5          C           1      USB  231
6          C           5   TYPE-C   35
7          C           8  MIC-USB   12
8          C           1    DRIVE    7

6.3 读写HTML文件

6.3.1 读取HTML表格方法read_html()方法
函数语法:

详细参数请查看官方文档:pandas.read_html()

Pandas.read_html(io,match='.+',flavor=None,header=None,index_col=None,skiprows=None,attrs=None)
  • io:表示路径对象
  • header:表示指定列标题所在的行
  • index_col:表示指定行标题对应的列
  • attrs:默认为None,用于表示表格的属性值
代码:

将使用read_html()方法读取http://gaokao.xdf.cn/201805/10781393.html的表格:

数据读取

import requests
import pandas as pd
html_data = requests.get('http://gaokao.xdf.cn/201805/10781393.html')
html_read = pd.read_html(html_data.content, encoding='utf-8')
print(html_read[0])
输出:
     0           1   2     3
0   排名        学校名称  省市    总分
1    1        清华大学  北京  95.3
2    2        北京大学  北京  78.6
3    3        浙江大学  浙江  73.9
4    4      上海交通大学  上海  73.1
..  ..         ...  ..   ...
95  94      中国政法大学  北京  37.6
96  96      大连医科大学  辽宁  37.5
97  97  中国石油大学(北京)  北京  37.3
98  98        西北大学  陕西  37.2
99  98      中国传媒大学  北京  37.2

[100 rows x 4 columns]
6.3.2 写入HTML表格方法to_html()方法
函数语法:

详细参数请查看官方文档:DataFrame.to_html()

DataFrame.to_html(buf,index,header)
  • buf:输出路径
  • index:行索引,默认为True
  • header:列索引,默认为True
代码:

将上文读取到的表格的前十名写入到test.html中,不保留行列索引:

html_read[0][:11].to_html('./test.html', index=False, header=False)
输出:
to_html

6.4 读写sql文件

Padnas支持Mysql、Oracle、SQLite等主流数据库的读写操作,为了高效读取数据库中的数据,需要引入SQLAlchemy软件,引入之后Pandas的io.sql模块将读写数据库,其中提供的常用函数如下表所示:

函数名称 说明
read_sql_table() 将读取的整张数据表中的数据转化成DataFrame对象
read_sql_query() 将sql语句读取的结果转换成DataFrame对象
read_sql() 上述两个函数的结合,既可以读数据表也可读SQL语句
to_sql() 将数据写入到SQL数据库中

本文将使用mysql数据库,Python需要使用:

pip install mysql-connector-python

如果使用的是Conda则需要使用:

conda install mysql-connector-python

安装模块。

6.4.1 写入数据库函数to_sql()
函数语法:

详细参数请查看官方文档:DataFrame.to_sql() Series.to_sql()

to_sql(name,con,schema=None,if_exists='fail',index=True,index_label=None,chunksize=None,dtype=None)
  • name:表示数据库表的名称
  • con:接收数据库连接信息
  • if_exists:可以取值为fail,replace,append等,默认为fail

在对数据库进行写入前需要首先创建数据库,使用mysql终端输入:

create database test;

创建test数据库。更多数据库指令参照:Sql教程 MySQL 教程

代码:

创建一个DataFrame对象并将其写入test数据库中的students表。

from sqlalchemy import create_engine
import pandas as pd
df = pd.DataFrame({
    "班级": ["一年级", "二年级", "三年级", "四年级"],
    "男生人数": [25, 23, 27, 30],
    "女生人数": [19, 17, 20, 20]
})
engine = create_engine("mysql+mysqlconnector://root:root@127.0.0.1:3306/test")
df.to_sql('students',engine)
输出:

通过在Mysql数据库中输入:

use test; /*使用test数据库*/
show tables; /*显示数据库中的数据表*/
select *from students; /*输出students数据表*/
to_sql

至此,表格已经创建成功了。

6.4.1 读取数据表函数read_sql()
函数语法:

详细参数请查看官方文档:pandas.read_sql()

pandas.read_sql(sql,con,index_col=None,coerce_float=True,params=None,parse_dates=None,columns=None,chunksize=None)
  • sql:表示被执行的SQL语句
  • con:接收数据库连接,表示数据库的连接信息
  • columns:从SQL表中选择列名列表

注意:通过create_engine()函数创建连接时,需要指定格式如下:'数据库类型+数据库驱动名称//用户名:密码@机器地址:端口号/数据库名'

代码:

读取上文中test/students数据表中的内容并写入名称为data_sqlDataFrame对象中。

from sqlalchemy import create_engine
import pandas as pd
engine = create_engine(
    "mysql+mysqlconnector://root:root@127.0.0.1:3306/test")
sql = "select *from students"
data_sql = pd.read_sql(sql, engine)
print(data_sql)
输出:
   index   班级  男生人数  女生人数
0      0  一年级    25    19
1      1  二年级    23    17
2      2  三年级    27    20
3      3  四年级    30    20
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容