学习 DataFrame 对象的高级技巧
- 学习 DataFrame 对象的高级技巧
- 替换数据
- 将函数应用于数据帧对象的列或行
- 查询数据帧对象中的行
- 获取数据帧对象数据的统计信息
学习 DataFrame 对象的高级技巧
在上一节中,我们讲解了可以对数据帧对象执行的基本操作。在本节中,我们将研究数据帧对象上的下一级别操作,以进行数据评估和转换。以下小节将讨论这些操作。
替换数据
一种常见的需求是用另一组值替换数字数据或字符串数据。pandas
库中有很多选项可以用来进行此类数据替换。这些操作最常用的方法是使用 at
方法。at
方法提供了一种访问或更新数据帧中任意单元格数据的简便方法。对于批量替换操作,也可以使用 replace
方法,我们可以通过多种方式使用该方法。例如,我们可以使用该方法将一个数字替换为另一个数字,或将一个字符串替换为另一个字符串,或者替换任何与正则表达式匹配的内容。此外,我们还可以使用该方法替换通过列表或字典提供的任何条目。在下面的代码示例中,我们将介绍大部分替换选项。在本代码示例中,我们将使用与之前代码示例中相同的数据帧对象。以下是示例代码:
import pandas as pdweekly_data = {'星期': ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日'],'温度':[40, 33, 42, 31, 41, 40, 30],'天气': ["晴天", "多云", "晴天", "下雨", "晴天", "多云", "下雨"]}df = pd.DataFrame(weekly_data)df.index = ['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN']print(df)
以上代码的输出结果是:
MON 星期一 40 晴天
TUE 星期二 33 多云
WED 星期三 42 晴天
THU 星期四 31 下雨
FRI 星期五 41 晴天
SAT 星期六 40 多云
SUN 星期日 30 下雨
接下来,我们用这个数据帧对象,一个个地讲解几个替换操作。
-
把数据帧中的出现的所有数字
40
替换为39
:df.replace(40,39, inplace=True)
-
把数据帧中所有的
晴天
替换为晴
:df.replace('晴天', '晴', inplace=True)
-
用正则表达式把满足条件的字符串替换为另一个,在这里是把
多云
替换为阴
:df.replace(to_replace="^多.*",value="阴",inplace=True,regex=True)
-
一次性使用一个字符串列表中的字符串替换另一个字符串列表中的列表的字符串。
df.replace(["星期一", "星期二"], ["周一", "周二"], inplace=True)
-
使用字典中的
键-值
对,替换所有字符串。键
是被替换的字符串,值
是替换字符串:df.replace({"星期三": "周三", "星期四": "周四"}, inplace=True)
-
使用两个字典,替换指定列中的字符串。在这两个字典中,
键
是列名字,值
是被替换的、替换的值,如下所示:df.replace({"星期": "星期五"}, {"星期" : "周五"}, inplace=True)
在这个语句中,前一个字典用来指名列名字和被替换的值,第二个字典用来指明同一个列和替换值。
-
使用嵌套字典,替换多个字符串,如下所示:
df.replace({"星期": {"星期六": "周六", "星期日": "周日"}, "天气": {"下雨": "大雨"}}, inplace=True)
在这个场景中,外部的字典(用星期
和 天气
做键)用来指明替换动作发生的列,内部字典用来指明被替换和替换字符串。
inplace=True
用来指明 replace
的输出数据帧对象就是输入数据帧对象。默认是inplace=False
。在这种情况下,每次调用 repalce
都不会修改原始数据帧,而是返回一个新的数据帧。
下面是完整的代码:
import pandas as pdweekly_data = {'星期': ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日'],'温度':[40, 33, 42, 31, 41, 40, 30],'天气': ["晴天", "多云", "晴天", "下雨", "晴天", "多云", "下雨"]}df = pd.DataFrame(weekly_data)df.index = ['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN']print(df)df.replace(40,39, inplace=True)df.replace("Sunny","Sun",inplace=True)df.replace(to_replace="^多.*",value="阴",inplace=True,regex=True)df.replace(["星期一", "星期二"], ["周一", "周二"], inplace=True)df.replace({"星期三": "周三", "星期四": "周四"}, inplace=True)df.replace({"星期": "星期五"}, {"星期" : "周五"}, inplace=True)df.replace({"星期": {"星期六": "周六", "星期日": "周日"}, "天气": {"下雨": "大雨"}}, inplace=True)print(df)
上面代码的输出结果是:
星期 温度 天气
MON 星期一 40 晴天
TUE 星期二 33 多云
WED 星期三 42 晴天
THU 星期四 31 下雨
FRI 星期五 41 晴天
SAT 星期六 40 多云
SUN 星期日 30 下雨星期 温度 天气
MON 周一 39 晴天
TUE 周二 33 阴
WED 周三 42 晴天
THU 周四 31 大雨
FRI 周五 41 晴天
SAT 周六 39 阴
SUN 周日 30 大雨
将函数应用于数据帧对象的列或行
有时,我们想在开始数据分析之前清理数据、调整数据或转换数据。有一种简单的方法,可以使用 apply
、applymap
或 map
方法在数据帧上应用某种类型的函数。apply
方法适用于列或行,而 applymap
方法则对整个数据帧逐个元素进行操作。相比之下,map
方法对单个序列中的逐个元素进行操作。现在,我们将讨论几个代码示例,以说明 apply
和 map
方法的使用。
将数据导入到数据帧对象以后,常常需要清理。这是是很常见的。例如,它可能有尾随或前导空格、新行字符或任何不需要的字符。通过在列序列上使用map
方法和lambda
函数,可以很容易地从数据中删除这些值。lambda
函数用于列的每个元素。在我们的代码示例中,首先,我们将删除尾随的空格、点和逗号。然后,我们将删除条件列的前导空格、下划线和破折号。
import pandas as pdweekly_data = {'星期': ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日'],'温度':[40, 33, 42, 31, 41, 40, 30],'天气': ["晴天,", "_多云", "--晴天", "- 下雨", "_-晴天.", "多云", "下雨 ,"]}df = pd.DataFrame(weekly_data)print("原始数据:")
print(df)# 清理 "天气" 列
df["天气"] = df["天气"].map(lambda x: x.lstrip('_- ').rstrip(',. '))# 把 "温度" 列改名为 "摄氏度"
df = df.rename(columns={'温度': '摄氏度'})# 添加 "华氏度" 列
df["华氏度"] = df["摄氏度"].apply(lambda x: x * 9.0 / 5.0 + 32)print("清理并整理后:")
print(df)
上面代码的输出结果是:
原始数据:星期 温度 天气
0 星期一 40 晴天,
1 星期二 33 _多云
2 星期三 42 --晴天
3 星期四 31 - 下雨
4 星期五 41 _-晴天.
5 星期六 40 多云
6 星期日 30 下雨 ,
清理并整理后:星期 摄氏度 天气 华氏度
0 星期一 40 晴天 104.0
1 星期二 33 多云 91.4
2 星期三 42 晴天 107.6
3 星期四 31 下雨 87.8
4 星期五 41 晴天 105.8
5 星期六 40 多云 104.0
6 星期日 30 下雨 86.0
查询数据帧对象中的行
要根据特定列中的值查询记录,一种常见的方法是使用 AND
或 OR
逻辑运算应用过滤器。然而,这种方法很快就会变得杂乱无章,无法满足简单的要求,例如搜索数值范围介于两个数值之间的记录。pandas
库提供了一种更简洁的工具:between
方法,它有点类似于 SQL
中的 between
关键字。
以下代码示例使用了与前一个示例中使用的 weekly_data
数据帧对象相同的对象。首先,我们将展示传统过滤器的使用,然后我们将展示如何使用 between
方法查询温度值在 30
到 40
之间的行:
import pandas as pdweekly_data = {'day': ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日'],'温度':[40, 33, 42, 31, 41, 40, 30],'天气': ["晴天", "多云", "晴天", "下雨", "晴天", "多云", "下雨"]}df = pd.DataFrame(weekly_data)print("使用逻辑表达式:")
print(df[(df.温度 >= 30) & (df.温度 <= 40)])
print("使用 between:")
print(df[df.温度.between(30, 40)])
上面代码的输出结果是:
使用逻辑表达式:day 温度 天气
0 星期一 40 晴天
1 星期二 33 多云
3 星期四 31 下雨
5 星期六 40 多云
6 星期日 30 下雨
使用 between:day 温度 天气
0 星期一 40 晴天
1 星期二 33 多云
3 星期四 31 下雨
5 星期六 40 多云
6 星期日 30 下雨
可以看到,两种方法的输出结果是一致的。
pandas
库也很好地支持基于文本数据查询行。这可以通过在数据帧对象的字符串类型列上使用 str
访问器来实现。例如,如果我们想根据一天的天气(如下雨或晴天)在 weekly_data
数据帧象中搜索行,我们可以编写一个传统的过滤器,也可以在包含以下内容的列上使用str
访问器方法。以下代码示例说明了如何使用这两个选项来获取天气列中具有 雨天
或 晴天
作为数据值的行:
import pandas as pdweekly_data = {'day': ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日'],'温度':[40, 33, 42, 31, 41, 40, 30],'天气': ["晴天", "多云", "晴天", "下雨", "晴天", "多云", "下雨"]}df = pd.DataFrame(weekly_data)print('使用逻辑表达式:')
print(df[(df.天气 =='下雨') | (df.天气=='晴天')])
print('使用 contains 方法:')
print(df[df['天气'].str.contains('下雨|晴天')])
上面代码的输出结果是:
使用逻辑表达式:day 温度 天气
0 星期一 40 晴天
2 星期三 42 晴天
3 星期四 31 下雨
4 星期五 41 晴天
6 星期日 30 下雨
使用 contains 方法:day 温度 天气
0 星期一 40 晴天
2 星期三 42 晴天
3 星期四 31 下雨
4 星期五 41 晴天
6 星期日 30 下雨
获取数据帧对象数据的统计信息
为了获得中心趋势、标准偏差和形状等统计数据,我们可以使用描述方法。数字列的描述方法的输出包括以下内容:
- count
- mean
- standard deviation
- min
- max
- 25th percentiles, 50th percentile, 75th percentile (第25百分位、第50百分位和第75百分位)
可以通过把所需的细分值赋值给 percentiles
参数来更改默认的百分位数细分。
如果把 describe
方法用于非数字数据,如字符串,我们将得到 count
、unique
、top
和 freq
。top
值是最常见的值,而freq
是最常见值频率。默认情况下,除非我们为include
参数提供适当的值,否则describe
方法只计算数值列。
在下面的代码示例中,我们将对同一 weekly_date
数据帧对象进行以下计算:
- 使用带有或不带有
include
参数的describe
方法; - 使用带有
percentiles
方法的describe
方法; - 使用
groupby
方法按列对数据进行分组,然后在其上使用describe
方法。
下面是完整的示例代码:
import pandas as pd
import numpy as npweekly_data = {'day': ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期日'],'温度':[40, 33, 42, 31, 41, 40, 30],'天气': ["晴天", "多云", "晴天", "下雨", "晴天", "多云", "下雨"]}df = pd.DataFrame(weekly_data)pd.set_option('display.max_columns', None)print('describe:')
print(df.describe())
print('describe with include=all:')
print(df.describe(include="all"))
print('describe with percentiles:')
print(df.describe(percentiles=np.arange(0, 1, 0.1)))
print('describe after groupby:')
print(df.groupby('天气').describe(percentiles=np.arange(0, 1, 0.1)))
上面代码的输出结果是:
describe:温度
count 7.000000
mean 36.714286
std 5.154748
min 30.000000
25% 32.000000
50% 40.000000
75% 40.500000
max 42.000000
describe with include=all:day 温度 天气
count 7 7.000000 7
unique 7 NaN 3
top 星期一 NaN 晴天
freq 1 NaN 3
mean NaN 36.714286 NaN
std NaN 5.154748 NaN
min NaN 30.000000 NaN
25% NaN 32.000000 NaN
50% NaN 40.000000 NaN
75% NaN 40.500000 NaN
max NaN 42.000000 NaN
describe with percentiles:温度
count 7.000000
mean 36.714286
std 5.154748
min 30.000000
0% 30.000000
10% 30.600000
20% 31.400000
30% 32.600000
40% 35.800000
50% 40.000000
60% 40.000000
70% 40.200000
80% 40.800000
90% 41.400000
max 42.000000
describe after groupby:温度 \count mean std min 0% 10% 20% 30% 40% 50% 60%
天气
下雨 2.0 30.5 0.707107 30.0 30.0 30.1 30.2 30.3 30.4 30.5 30.6
多云 2.0 36.5 4.949747 33.0 33.0 33.7 34.4 35.1 35.8 36.5 37.2
晴天 3.0 41.0 1.000000 40.0 40.0 40.2 40.4 40.6 40.8 41.0 41.2 70% 80% 90% max
天气
下雨 30.7 30.8 30.9 31.0
多云 37.9 38.6 39.3 40.0
晴天 41.4 41.6 41.8 42.0
请注意,我们在开始时更改了pandas
库的max_columes
选项,以便在控制台输出中显示我们期望的所有列。如果没有这个,groupby
方法的控制台输出中的一些列将被截断。
<完>