一、 什么是Pandas?

Pandas的名称来自于面板数据(panel data),Pandas是一个强大的分析结构化数据的工具集,基于NumPy构建,提供了高级数据结构和数据操作工具,它是使Python成为强大而高效的数据分析环境的重要因素之一。Pandas有以下几个特点:

  • 是一个强大的分析和操作大型结构化数据集所需的工具集
  • 基础是NumPy,提供了高性能矩阵的运算
  • 提供了大量能够快速便捷地处理数据的函数和方法
  • 应用于数据挖掘,数据分析
  • 提供数据清洗功能

二、为什么要学习pandas

numpy已经能够帮助我们处理数据,能够结合matplotlib解决我们数据分析的问题,那么pandas学习的目的在什么地方呢?

numpy虽能够处理数值型数据,但是很多时候数据除了数值之外,还需要处理字符串、时间序列等。比如:我们通过爬虫获取到了存储在数据库中的数据,所以,pandas出现了。

pandas官网:https://pandas.pydata.org/,首先先来认识pandas中的两个常用的类

  • Series(一维数据)
  • DataFrame(二维数据)

三、Series

3.1 Series的创建

Series是一个一维的结构,创建Series的语法:

pd.Series();

常用的几个参数:

  • index,用于指定新的索引,例如pd.Series(arr1,index=[‘a’,‘b’,‘c’,‘d’,‘e’])以a,b,c,d,e作为行索引;
  • dtype,用于指定元素的数据类型;

3.1.1 通过列表或者一维数组创建

import numpy as np
import pandas as pd

# 1.通过list创建一维数组
s1 = pd.Series([1, 2, 3, 4, 5])
print(s1)
"""
0    1
1    2
2    3
3    4
4    5
dtype: int64
"""

# 2.通过numpy一维数组创建,pandas一维数组
arr = np.arange(1, 6)
s2 = pd.Series(arr)
print(s2)
"""
0    1
1    2
2    3
3    4
4    5
dtype: int32
"""

3.1.2 通过字典创建

import pandas as pd

dt = {'name': '范闲', 'age': 16, 'sex': '男'}
s3 = pd.Series(dt)
print(s3)
"""
name    范闲
age     16
sex      男
dtype: object
"""

# 通过字典创建数组的时候也可以指定索引,索引和字典键相同才有效,否则默认为 NaN
s4 = pd.Series(dt,index=['name', 'age', 'sex', 'class'])
print(s4)
"""
name      范闲
age       16
sex        男
class    NaN
dtype: object
"""

3.2 Series的基本用法

3.2.1.Series常用属性

Series的常用属性:

  • shape 返回形状
  • size 返回元素个数
  • index 返回索引值
  • values 返回值
  • dtype 元素的类型

用法示例:

import pandas as pd

# 创建pandas.Series对象
s = pd.Series(data=[1, 2, 3, 4, 'five'], index=['a', 'b', 'c', 'd', 'e'])
print(s.shape)  # 返回形状:(5,)
print(s.dtype)  # 返回元素类型:object
print(s.size)  # 返回元素个数: 5
print(s.index)  # 返回索引值: Index(['a', 'b', 'c', 'd', 'e'], dtype='object')
print(s.values)  # 返回值: [1 2 3 4 'five']

3.2.2.索引取值

Series和DataFrame中的索引都是Index对象,索引对象不可变,保证了数据的安全。常见的Index种类:

  • Index,索引
  • Int64Index,整数索引
  • MultiIndex,层级索引
  • DatetimeIndex,时间戳类型
import pandas as pd

dt = {'name': '范闲', 'age': 16, 'sex': '男'}
s3 = pd.Series(dt)
print(s3)
"""
name    范闲
age     16
sex      男
dtype: object
"""

# 根据索引取值,使用 s3[0] 按位置访问元素的方法已被弃用,使用会报提示
# print(s3[0])
# 现在推荐使用.iloc 方法按位置访问元素
print(s3.iloc[0])  # 范闲

print(s3.iloc[0:2])
"""
name    范闲
age     16
dtype: object
"""

3.2.3.Series的常用方法:

⑴.head() 和 tail():

  • head(n): 返回前 n 个元素,默认是 5 个。
  • tail(n): 返回后 n 个元素,默认是 5 个。
import pandas as pd

s = pd.Series([1, 2, 3, 4, 5, 6])
print(s.head(3))  # 输出前 3 个元素
"""
0    1
1    2
2    3
dtype: int64
"""
print(s.tail(3))  # 输出后 3 个元素
"""
3    4
4    5
5    6
dtype: int64
"""

⑵.unique():

  • 返回 Series 中唯一值的数组。
import pandas as pd

s2 = pd.Series([1, 2, 2, 3, 4, 4, 5])
print(s2.unique())  # 输出: [1 2 3 4 5]

⑶.isnull() 和 notnull():

  • isnull(): 检查 Series 中是否有缺失值,返回一个布尔 Series
  • notnull(): 检查 Series 中是否没有缺失值,返回一个布尔 Series
import pandas as pd

s = pd.Series([1, 2, None, 4, None])
print(s.isnull())  # 输出: [False False  True False  True]
print(s.notnull())  # 输出: [ True True False True False]

⑷.add()、sub()、mul()、div():

这些方法用于按元素执行算术运算:

  • add(): 加法
  • sub(): 减法
  • mul(): 乘法
  • div(): 除法
import pandas as pd

s1 = pd.Series([1, 2, 3])
s2 = pd.Series([4, 5, 6])

print(s1.add(s2))  # 输出: [5, 7, 9]
print(s1.sub(s2))  # 输出: [-3, -3, -3]
print(s1.mul(s2))  # 输出: [4, 10, 18]
print(s1.div(s2))  # 输出: [0.25, 0.4, 0.5]

3.2.4.Series的算术运算:

pandas.Series 中进行算术运算时,确保了索引一致的元素会进行算数运算,而对于不一致的索引,则会补空(NaN)。这种处理方式称为对齐(alignment)。举例来说,假设有两个 Series 对象 s1s2

import pandas as pd

s1 = pd.Series([1, 2, 3], index=['a', 'b', 'c'])
s2 = pd.Series([4, 5, 6], index=['b', 'c', 'd'])

# 算术运算时,对齐索引进行操作,不一致的索引会补空(NaN)
result = s1 + s2
print(result)
"""
result输出:
a    NaN
b    6.0
c    8.0
d    NaN
dtype: float64
"""

解释一下这个结果:

  • s1 中的索引有 'a', 'b', 'c',而 s2 中的索引有 'b', 'c', 'd'
  • 在进行加法运算时,对应的索引 'b''c' 对应的元素分别是 23,所以结果为 2 + 4 = 63 + 5 = 8
  • 对于索引 'a''d',因为只存在于其中一个 Series 中,所以在结果中显示为 NaN(空值)。

这种对齐操作使得 pandas.Series 在处理数据时非常灵活和方便,特别是在处理来自不同数据源或者部分缺失数据的情况下,能够保证结果的一致性和可靠性。

四、DataFrame

DataFrame 是一个【表格型】的数据结构。DataFrame 由按一定顺序排列的多列数据组成。设计初衷是将 Series 的使用场景从一维扩展到二维。在 DataFrame 中,每一列可以是不同的数据类型(例如整数、浮点数、字符串等),且每一列本质上是一个 SeriesDataFrame 可以看作是共享同一个索引的多个 Series 组成的结构。

主要特点:

  • 二维数据结构:DataFrame 是二维的,可以看作一个电子表格或 SQL 表。
  • 按标签或整数索引:可以通过标签(列名)或整数索引访问数据。
  • 不同数据类型的列:每一列可以是不同的数据类型。

4.1.DateFrame创建

4.1.1.字典类

import numpy as np
import pandas as pd

# 数组、列表或元组构成的字典构造dataframe
# 注意:所有数组的长度必须相同
data = {
    "a": [1, 2, 3, 4, 5],
    "b": (5, 6, 7, 8, 9),
    "c": np.arange(9, 14)
}

# 构造dataframe
df = pd.DataFrame(data)
print(df)
"""
   a  b   c
0  1  5   9
1  2  6  10
2  3  7  11
3  4  8  12
4  5  9  13
"""

上面结果发现:DataFrame既有行索引,也有列索引。

  • 行索引:index
  • 列索引:columns
  • 值:values
import numpy as np
import pandas as pd

# 数组、列表或元组构成的字典构造dataframe
# 注意:所有数组的长度必须相同
data = {
    "a": [1, 2, 3, 4, 5],
    "b": (5, 6, 7, 8, 9),
    "c": np.arange(9, 14)
}

# 构造dataframe
df = pd.DataFrame(data)
"""
   a  b   c
0  1  5   9
1  2  6  10
2  3  7  11
3  4  8  12
4  5  9  13
"""

# index属性查看行索引
print(df.index)  # RangeIndex(start=0, stop=5, step=1)

# columns属性查看列索引
print(df.columns)  # Index(['a', 'b', 'c'], dtype='object')

# values属性查看值
print(df.values)
"""
[[ 1  5  9]
 [ 2  6 10]
 [ 3  7 11]
 [ 4  8 12]
 [ 5  9 13]]
 """

# 指定index
df2 = pd.DataFrame(data, index=['A', 'B', 'C', 'D', 'E'])
print(df2)
"""
   a  b   c
A  1  5   9
B  2  6  10
C  3  7  11
D  4  8  12
E  5  9  13
"""

4.1.2.列表类

import numpy as np
import pandas as pd

# Series构成的字典构造dataframe
dt = pd.DataFrame({'a': pd.Series(np.arange(3)), 'b': pd.Series(np.arange(3, 5))})
print(dt)
"""
   a    b
0  0  3.0
1  1  4.0
2  2  NaN
"""

4.2.DataFrame的基本用法

4.2.1.T转置

pandas 中,.T 属性可以用来转置一个 DataFrame。转置操作会将行和列进行互换。

import numpy as np
import pandas as pd

pd1 = pd.DataFrame(np.arange(9).reshape(3, 3), index=['a', 'b', 'c'], columns=['A', 'B', 'C'])
"""
   A  B  C
a  0  1  2
b  3  4  5
c  6  7  8
"""
print("*****************T转置*****************")
print(pd1.T)
"""
   a  b  c
A  0  3  6
B  1  4  7
C  2  5  8
"""

可以看到,转置后的 DataFrame 中,原来的行变成了列,原来的列变成了行。注意事项:

  • 如果 DataFrame 的列和行标签都是唯一的,转置操作是非常直观的。
  • 对于大型 DataFrame,转置操作可能会消耗较多内存和计算资源,因此需要根据实际情况评估性能。

4.2.2.通过列索引获取列数据(Series类型)

pandas 中,可以通过列索引来获取特定列的数据,返回的结果是一个 Series 类型。可以使用多种方法来实现这一点,包括使用中括号 []、点符号 .loc/iloc 属性。下面是一些示例:

import numpy as np
import pandas as pd

pd1 = pd.DataFrame(np.arange(9).reshape(3, 3), index=['a', 'b', 'c'], columns=['A', 'B', 'C'])
"""
   A  B  C
a  0  1  2
b  3  4  5
c  6  7  8
"""

# 方法 1: 使用中括号 []
column_A = pd1['A']
print(column_A)
"""
a    0
b    3
c    6
Name: A, dtype: int32
"""
print(type(column_A))  # <class 'pandas.core.series.Series'>

# 方法 2: 使用点符号 .
# 获取列 'B' 的数据
column_B = pd1.B
print(column_B)
"""
a    1
b    4
c    7
Name: B, dtype: int32
"""
print(type(column_B))  # <class 'pandas.core.series.Series'>

# 方法 3: 使用 loc 属性(上面index设置的索引就可以通过loc取值)
# 获取列 'C' 的数据
column_C = pd1.loc[:, 'C']
print(column_C)
"""
a    2
b    5
c    8
Name: C, dtype: int32
"""
print(type(column_C))  # <class 'pandas.core.series.Series'>

# 方法 4: 使用 iloc 属性 (通过列的索引位置)
# 获取第一列 (索引位置为 0) 的数据
column_0 = pd1.iloc[0]
print(column_0)
"""
A    0
B    1
C    2
Name: a, dtype: int32
"""
print(type(column_0))  # <class 'pandas.core.series.Series'>

pandas 中,使用 loc 属性时,冒号 : 有选择行或列的范围的作用。具体来说,冒号可以用于选择整个行或列。在 DataFrame 中,loc 属性的基本语法是 df.loc[row_selection, column_selection]。冒号 : 的作用

  • 在行选择中使用冒号 : 可以选择所有行。
  • 在列选择中使用冒号 : 可以选择所有列。

4.2.3.增加列数据

pandas 中,可以通过多种方法向 DataFrame 中添加新列。下面是一些常用的方法:

方法 1: 直接赋值

通过直接赋值的方式增加新列:

import numpy as np
import pandas as pd

pd1 = pd.DataFrame(np.arange(9).reshape(3, 3), index=['a', 'b', 'c'], columns=['A', 'B', 'C'])
"""
   A  B  C
a  0  1  2
b  3  4  5
c  6  7  8
"""
# 方法 1: 直接赋值
pd1['D'] = [9, 10, 11]
# 输出增加新列后的 DataFrame
print(pd1)
"""
   A  B  C   D
a  0  1  2   9
b  3  4  5  10
c  6  7  8  11
"""
方法 2: 使用 assign 方法

通过 assign 方法增加新列:

import numpy as np
import pandas as pd

pd1 = pd.DataFrame(np.arange(9).reshape(3, 3), index=['a', 'b', 'c'], columns=['A', 'B', 'C'])
"""
   A  B  C
a  0  1  2
b  3  4  5
c  6  7  8
"""
# 增加新列 'E' 并创建新的 DataFrame
pd2 = pd1.assign(E=[12, 13, 14])
# 输出增加新列后的 DataFrame
print(pd2)
"""
   A  B  C   E
a  0  1  2  12
b  3  4  5  13
c  6  7  8  14
"""
方法 3: 使用 insert 方法

通过 insert 方法在特定位置插入新列:

import numpy as np
import pandas as pd

pd1 = pd.DataFrame(np.arange(9).reshape(3, 3), index=['a', 'b', 'c'], columns=['A', 'B', 'C'])
"""
   A  B  C
a  0  1  2
b  3  4  5
c  6  7  8
"""
# 在索引位置 1 处插入新列 'F'
pd1.insert(1, "F", [12, 13, 14])
# 输出增加新列后的 DataFrame
print(pd1)
"""
   A   F  B  C
a  0  12  1  2
b  3  13  4  5
c  6  14  7  8
"""
方法 4: 根据现有列计算新列

根据现有列的数据计算新列:

import numpy as np
import pandas as pd

pd1 = pd.DataFrame(np.arange(9).reshape(3, 3), index=['a', 'b', 'c'], columns=['A', 'B', 'C'])
"""
   A  B  C
a  0  1  2
b  3  4  5
c  6  7  8
"""
# 计算列 'G',其值为列 'A' 和列 'B' 之和
pd1['G'] = pd1['A'] + pd1['B']
# 输出增加新列后的 DataFrame
print(pd1)
"""
   A  B  C   G
a  0  1  2   1
b  3  4  5   7
c  6  7  8  13
"""

4.2.4.删除列

pandas 中,可以通过多种方法删除 DataFrame 中的列。下面介绍几种常用的方法:

方法 1: 使用 drop 方法

使用 drop 方法删除列:

import numpy as np
import pandas as pd

pd1 = pd.DataFrame(np.arange(9).reshape(3, 3), index=['a', 'b', 'c'], columns=['A', 'B', 'C'])
"""
   A  B  C
a  0  1  2
b  3  4  5
c  6  7  8
"""
# 删除列 'B'
pd1_drop = pd1.drop(columns=['B'])
print(pd1_drop)
"""
   A  C
a  0  2
b  3  5
c  6  8
"""
方法 2: 使用 del 关键字

使用 del 关键字删除列:

import numpy as np
import pandas as pd

pd1 = pd.DataFrame(np.arange(9).reshape(3, 3), index=['a', 'b', 'c'], columns=['A', 'B', 'C'])
"""
   A  B  C
a  0  1  2
b  3  4  5
c  6  7  8
"""
# 使用 del 删除列 'C'
del pd1['C']
print(pd1)
"""
   A  B
a  0  1
b  3  4
c  6  7
"""
方法 3: 使用 pop 方法

使用 pop 方法删除并返回指定列:

import numpy as np
import pandas as pd

pd1 = pd.DataFrame(np.arange(9).reshape(3, 3), index=['a', 'b', 'c'], columns=['A', 'B', 'C'])
"""
   A  B  C
a  0  1  2
b  3  4  5
c  6  7  8
"""
# 使用 pop 删除并返回列 'A'
column_A = pd1.pop('A')
print(column_A)
"""
a    0
b    3
c    6
Name: A, dtype: int32
"""
print(pd1)
"""
   B  C
a  1  2
b  4  5
c  7  8
"""
方法 4: 使用索引方式

直接使用索引方式删除列:

import numpy as np
import pandas as pd

pd1 = pd.DataFrame(np.arange(9).reshape(3, 3), index=['a', 'b', 'c'], columns=['A', 'B', 'C'])
"""
   A  B  C
a  0  1  2
b  3  4  5
c  6  7  8
"""
# 使用索引方式删除列 'B'
pd1 = pd1.drop(columns=['B'])
print(pd1)
"""
   A  C
a  0  2
b  3  5
c  6  8
"""

详细说明

  • 使用 drop 方法:pd1.drop(columns=['B']) 删除列 'B' 并返回一个新的 DataFrame,原始 DataFrame 不变。
  • 使用 del 关键字:del pd1['C'] 直接从原始 DataFrame 中删除列 'C',原地操作,不返回新的 DataFrame。
  • 使用 pop 方法:pd1.pop('A') 删除并返回列 'A',原地操作,同时返回被删除的列。
  • 直接使用索引方式:pd1 = pd1.drop(columns=['B']) 同样是使用 drop 方法删除列 'B',但这里将结果重新赋值给原始 DataFrame。

4.3.DataFrame常用的属性

values、columns、index、shape用法和series差不多直接调用即可

  • values:返回 DataFrame 的数据部分,二维 numpy 数组。
  • columns:返回 DataFrame 的列标签,类型为 Index。
  • index:返回 DataFrame 的行索引标签,类型为 Index。
  • shape:返回 DataFrame 的维度信息,即行数和列数的元组。
import numpy as np
import pandas as pd

pd1 = pd.DataFrame(np.arange(9).reshape(3, 3), index=['a', 'b', 'c'], columns=['A', 'B', 'C'])
"""
   A  B  C
a  0  1  2
b  3  4  5
c  6  7  8
"""
# 使用values:返回 DataFrame 的数据部分,二维 numpy 数组。
print(pd1.values)
"""
[[0 1 2]
 [3 4 5]
 [6 7 8]]
"""

# columns 属性返回 DataFrame 的列标签(列名)。
print(pd1.columns)  # Index(['A', 'B', 'C'], dtype='object')

# index 属性返回 DataFrame 的行索引标签。
print(pd1.index)  # Index(['a', 'b', 'c'], dtype='object')

# shape 属性返回 DataFrame 的维度信息,即行数和列数。
print(pd1.shape)  # (3, 3)

4.4.DataFrame索引操作

4.4.1.对列进行索引

import numpy as np
import pandas as pd

pd1 = pd.DataFrame(data=np.random.randint(50, 100, size=(3, 4)), columns=['a', 'b', 'c', 'd'])
print(pd1)
"""
    a   b   c   d
0  55  73  64  62
1  67  75  60  54
2  71  95  87  51
"""
# 取单列,如果pd1有显示的索引,通过索引机制取行或者列的时候只可以使用显示索引
print(pd1['a'])
"""
0    55
1    67
2    71
Name: a, dtype: int32
"""
# 取多列
print(pd1[['a', 'c']])
"""
    a   c
0  55  64
1  67  60
2  71  87
"""

4.4.2.对行进行索引和对元素进行索引

  • iloc:通过隐式索引取行
  • loc:通过显示索引取行
import numpy as np
import pandas as pd

pd1 = pd.DataFrame(data=np.random.randint(50, 100, size=(3, 4)), columns=['a', 'b', 'c', 'd'])
print(pd1)
"""
    a   b   c   d
0  82  66  51  80
1  78  53  74  64
2  89  71  82  97
"""
# 取单行,这里的pd1行索引为隐式索引(没有指定索引),用iloc或loc都可以
print(pd1.iloc[0])
"""
a    82
b    66
c    51
d    80
Name: 0, dtype: int32
"""
# 取多行
print(pd1.iloc[[0, 2]])  # 取第0行和第2行
"""
    a   b   c   d
0  82  66  51  80
2  89  71  82  97
"""

# 取单个元素
print(pd1.iloc[0, 2])  # 取第0行第2列的元素  51

# 取多个元素
print(pd1.iloc[[0, 2], 2])  # 取第0行和第2行的第二列元素
"""
0    51
2    82
Name: c, dtype: int32
"""

4.5.DataFrame的切片操作

import numpy as np
import pandas as pd

pd1 = pd.DataFrame(data=np.random.randint(50, 100, size=(6, 4)), columns=['a', 'b', 'c', 'd'])
print(pd1)
"""
    a   b   c   d
0  95  57  67  62
1  58  81  59  79
2  81  80  66  69
3  51  73  69  50
4  54  75  58  60
5  78  56  96  63
"""
# 切行(切取索引0-3行下面两种方式结果相同)
print(pd1[0:4])
print(pd1.iloc[0:4])
"""
    a   b   c   d
0  95  57  67  62
1  58  81  59  79
2  81  80  66  69
3  51  73  69  50
"""
# 切列
print(pd1.iloc[:, 0:2])
"""
    a   b
0  95  57
1  58  81
2  81  80
3  51  73
4  54  75
5  78  56
"""

DataFrame索引和切片操作:
⑴.索引:

df[col]:取列
df.loc[index]:取行
df.iloc[index,col]:取元素

⑵.切片:

df[index1:index3]:切行
df.iloc[:,col1:col3]:切列