「这是我参与2022首次更文挑战的第9天,活动详情查看:2022首次更文挑战」。
Pandas 介绍
Pandas 是一个第三方模块,专门用来数据处理。Pandas 有很多强大的功能,我们可以用来处理 csv 和 excel 文件。我们可以用它进行数据的统计、查找等操作。因为是第三方模块,使用前我们需要安装一下:
pip install pandas
然后我们可以尝试一下 Pandas 的基本操作了。我们先看下面的代码:
import pandas as pd
# 创建一个 DataFrame 对象
df = pd.DataFrame([
{'city': '南昌', 'temperature': 2},
{'city': '武汉', 'temperature': -1}
])
print(df)
在代码中,我们创建了一个 DataFrame 对象,什么是 DataFrame 这个我们在后面会详细说。参数我们传入了一个元素为字典的列表,我们看一下输出结果:
city temperature
0 南昌 2
1 武汉 -1
可以看到显示效果类似于一张表,而且输出为我们添加了一个行索引。如果你使用 Jupyter 的话,显示效果会更加美观。 上面我们只是把全部数据输出,我们也可以选择性输出:
import pandas as pd
# 创建一个 DataFrame 对象
df = pd.DataFrame([
{'city': '南昌', 'temperature': 2},
{'city': '武汉', 'temperature': -1}
])
print(df.head(1))
这次我们调用了一个 df.head() 方法,传入参数 1,表示从头开始取 1 行数据,输出结果如下:
city temperature
0 南昌 2
除了查看整行数据,我们还可以索引特定的列:
import pandas as pd
# 创建一个 DataFrame 对象
df = pd.DataFrame([
{'city': '南昌', 'temperature': 2},
{'city': '武汉', 'temperature': -1}
])
print(df['city'])
比如上面代码我们就索引了 city 列,输出结果如下:
0 南昌
1 武汉
Name: city, dtype: object
除了这种普通方式,我们还可以进行条件索引。详细的操作会在后续讲到,下面我们就正式来看看 pandas 的操作吧!
Pandas 的数据结构
数据结构我们可以理解为数据类型,也就是 Pandas 中定义的一些特殊类型。其中有两个我们经常会使用到,一个是 Series,另外一个就是我们上面使用到的 DataFrame 了。那它们都是什么呢?又都有什么区别呢?
Series
其实 Series 就是一个一维的数据,它类似与一个列表,但是又和列表又很多不同。我们先看下面的代码:
import pandas as pd
# 创建一个 Series 对象
s = pd.Series([1, 2, 3, 4], dtype='float32')
print(s)
在创建 Series 时,我们指定了一个 dtype 参数,也是就 Series 的数据类型。dtype 参数不是必须的,当指定 dtype 参数后我们的 Series 对象只能存储指定类型的数据。这也是它和 list 不同的地方。
下面是输出结果:
0 1.0
1 2.0
2 3.0
3 4.0
dtype: float32
那我们来看看 Series 有些什么操作:
import pandas as pd
# 创建 Series 对象
s = pd.Series([1, 2, 3, 4, 4, 4], dtype='float32')
# 查看头一行元素
print(s.head(1))
# 计算 Series 长度
print(s.count())
# 查看数据类型
print(s.dtype)
# 查看数据
print(s.values)
# 查看索引
print(s.index)
# 查看数据大小(和 cout 类似)
print(s.size)
下面是输出结果:
0 1.0
dtype: float32
6
float32
[1. 2. 3. 4. 4. 4.]
6
RangeIndex(start=0, stop=6, step=1)
这里又几个需要注意,其中 s.values 获取的是一个 ndarray 对象。而 index 获取的是 Series 的索引,是一个 pandas.core.indexes.range.RangeIndex 对象,这是 Pandas 中定义的一个特殊对象。
除了上面的操作,Series 还有许多统计函数:
import pandas as pd
s = pd.Series([1, 2, 3, 4, 4, 4], dtype='float32')
# 求平均值
print(s.mean())
# 求最大值
print(s.max())
# 求最小值
print(s.min())
# 求标准差
print(s.std())
输出结果如下:
3.0
4.0
1.0
1.264911
上面的操作很好理解,这里就不解释了。下面我们看看 Series 的索引和切片操作,这是我们经常会使用的操作:
import pandas as pd
s = pd.Series(['a', 'b', 'c', 'd', 'e', 'f'])
# 索引
print(s[3])
# 切片
print(s[0: 2])
# 用 iloc 索引和切片
print(s.iloc[0])
print(s.iloc[0: 2])
# 用 loc 索引和切片
print(s.loc[0])
print(s.loc[0: 2])
# 通过值来索引切片
print(s.loc['a':'c'])
上面我们用了四种方式索引切片,其中[]是最简单的。而 iloc 和 loc 是 Pandas 提供的两个方法,它们都可以用来索引切片。两个方法都可以通过下标索引切片,但是如果想通过内容索引切片,则需要使用 loc 方法。
在上面介绍的很多方法,在 DataFrame 中也是通用的。我们后面会说到,下面我们来看看 DataFrame。
DataFrame
DataFrame 相当于一个二维表,相比 Series,DataFrame 的使用频率要高得多。我们先看看如何创建一个 DataFrame 对象:
import pandas as pd
# 创建一个 DataFrame 对象
df = pd.DataFrame([
{'city': '南昌', 'temperature': 2},
{'city': '武汉', 'temperature': -1}
])
print(df['city'])
这段代码在上面我们已经演示过了。而在上面提到的统计函数,索引切片在 DataFrame 中也是有的,但是因为是二维的表,因此会有些不同。我们来详细看看,首先我们创建 DataFrame 可以指定行列索引:
import pandas as pd
df = pd.DataFrame([
['南昌', 2],
['武汉', -1]
], columns=['city', 'temperature'], index=[0, 1])
print(df)
输出效果如下:
city temperature
0 南昌 2
1 武汉 -1
和之前一样。另外我们可以查看一些属性:
import pandas as pd
df = pd.DataFrame([
['南昌', 2],
['武汉', -1]
], columns=['city', 'temperature'], index=[0, 1])
print(df.shape)
print(df.index)
print(df.columns)
print(df.values)
print(df.T)
输出结果如下:
(2, 2)
Int64Index([0, 1], dtype='int64')
Index(['city', 'temperature'], dtype='object')
[['南昌' 2]
['武汉' -1]]
0 1
city 南昌 武汉
temperature 2 -1
前面几个很好理解,就是 df.T 看起来有点奇怪,不过仔细观察发现它就是原来的数据旋转 x、y 对换的结果,也就是转置。
下面我们来看看 DataFrame 的索引:
import pandas as pd
df = pd.DataFrame([
['南昌', 2],
['武汉', -1]
], columns=['city', 'temperature'], index=[0, 1])
print(df.loc[:, 'city'])
print(df.loc[:, 'city':'temperature'])
上面我们使用 loc 函数索引,它在 DataFrame 中的作用是按值索引。其中:
df.loc[:, 'city']
表示索引所有行的 city,而:
df.loc[:, 'city':'temperature']
表示索引所有行的 city 到 temperature。因为我的数据只有两列,所有输出结果如下:
0 南昌
1 武汉
Name: city, dtype: object
city temperature
0 南昌 2
1 武汉 -1
然后是用 iloc 函数进行下标索引:
import pandas as pd
df = pd.DataFrame([
['南昌', 2],
['武汉', -1]
], columns=['city', 'temperature'], index=[0, 1])
print(df.iloc[1:, :])
print(df.iloc[:, 1:])
含义是和 loc 差不多,只是 iloc 是通过数字下标进行索引,输出结果如下:
city temperature
1 武汉 -1
temperature
0 2
1 -1
从 csv 文件读取数据
上面我们简单介绍了一下 Series 和 DataFrame 类型。在我们实际使用时,通常会选择从本地的 csv 文件获取 DataFrame 对象,下面我们来看看如何操作,先准备一个简单的 csv 文件:
city,temperature
南昌,2
武汉,-1
读取文件的代码如下:
import pandas as pd
df = pd.read_csv('test.csv')
print(df)
我们调用 read_csv 文件,然后传入文件路径。输出结果如下:
city temperature
0 南昌 2
1 武汉 -1
显示效果和之前是一样的。读取文件后,我们就可以对数据进行上面的操作了。当然,我们可以对数据修改后再保存到文件:
import pandas as pd
df = pd.read_csv('test.csv')
df = df.drop('city', axis=1)
df.to_csv('test.csv')
在读取文件后,我们调用了 drop 函数,删除 city 列,其中 axis 参数等于 1 表示删除列。然后调用 to_csv 保存到文件。
条件查询
我们还可以进行一些带条件的查询,我们使用一个新的 DataFrame 对象:
import pandas as pd
df = pd.DataFrame([
{'city': '南昌', 'temperature': 2},
{'city': '武汉', 'temperature': -1},
{'city': '上海', 'temperature': 1},
])
print(df[df['temperature'] > 0])
其中:
df[df['temperature'] > 0]
表示查询温度大于 0 度的数据。输出结果如下:
city temperature
0 南昌 2
2 上海 1
我们也可以指定多个条件:
import pandas as pd
df = pd.DataFrame([
{'city': '南昌', 'temperature': 2},
{'city': '武汉', 'temperature': -1},
{'city': '上海', 'temperature': 1},
])
print(df[(df['temperature'] > 0) & (df['temperature'] < 2)])
在上面代码中,我们查找了温度大于 0,且小于 2 的数据。这里需要注意一下
df['temperature'] > 0
会返回一个 bool 数组,我们可以用 df 索引这个数组,就是获取符合条件的数据。而多条件则是通过&或|连接。下面是代码的输出结果:
city temperature
2 上海 1
上面的操作叫做布尔索引,这个在 NumPy 中也有。除了通过布尔索引,我们还可以通过 query 方法实现:
import pandas as pd
df = pd.DataFrame([
{'city': '南昌', 'temperature': 2},
{'city': '武汉', 'temperature': -1},
{'city': '上海', 'temperature': 1},
])
print(df.query('temperature > 0'))
我们在 query 中传入条件,其中条件需要是字符串。下面是输出结果:
city temperature
0 南昌 2
2 上海 1
query 通用可以多条件索引,也是通过& 和 |来连接。
import pandas as pd
df = pd.DataFrame([
{'city': '南昌', 'temperature': 2},
{'city': '武汉', 'temperature': -1},
{'city': '上海', 'temperature': 1},
])
print(df.query('temperature > 0 & temperature < 2'))
结果和上面的方式是一样的。