Python数据分析___Pandas基础1
Python数据分析
1、conda基本操作
conda create -n 虚拟环境名 python=3.8
conda env list 显示版本列表
conda activate py38 #切换到py38版本
conda deactivate 退出虚拟环境
conda remove -n 环境名 --all 删除虚拟环境
conda报错
2、2.1 pandas
1)DataFrame
- 用来处理结构化数据(SQL数据表,Excel表格)
- 可以简单理解为一张数据表(带有行标签和列标签)
2)Series
- 用来处理单列数据,也可以以把DataFrame看作由Series对象组成的字典或集合
- 可以简单理解为数据表的一行或一列
#加载csv和tsv数据
pd.read_csv('./data/xxx.csv')
pd.read_csv('./data/xxx.tsv',sep='\t')
#获取行标签
china.index
#获取列标签
china.cloumns
#设置某一列为行标签索引 不改变原数据
china.set_index('years')
2.2 DataFrame
2.2.1 DataFrame创建方式
字典创建
peoples = pd.DataFrame({
'Name': ['Smart', 'David'],
'Occupation': ['Teacher', 'IT Engineer'],
'Age': [18, 30]
})
peoples
使用colums参数指定列的顺序
使用 index 参数来指定行标签
2.2.2 DataFrame常用方法
| 属性或方法 | 说明 |
|---|---|
df.shape |
查看 DataFrame 数据的形状 |
df.size |
查看 DataFrame 数据元素的总个数 |
df.ndim |
查看 DataFrame 数据的维度 |
len(df) |
获取 DataFrame 数据的行数 |
df.index |
获取 DataFrame 数据的行标签 |
df.columns |
获取 DataFrame 数据的列标签 |
df.dtypes |
查看 DataFrame 每列数据元素的类型 |
df.info() |
查看 DataFrame 每列的结构 |
#获取行标签
china.index
#获取列标签
china.columns
#设置行标签 返回新值
china_df = china.set_index('year')
# describe演示
# include 参数设置显示非数值型列的统计信息
scientists.describe(include=[np.object_])

2.2.3 行标签和列标签操作
# 设置 Name 列的值作为行标签
scientists_df = scientists.set_index('Name',inplace= True)
scientists_df
# 注意:reset_index返回的是一个新的 DataFrame
scientists_df.reset_index()
加载数据后,修改行标签和列标签
加载
scientists.csv数据时,将 Name 列设置为行标签
pd.read_csv('./data/scientists.csv', index_col='Name')
或
pd.read_csv('./data/scientists.csv', index_col=0)
使用
rename修改行标签和列标签
index_name = {'Rosaline Franklin': 'rosaline franklin', 'John Snow': 'john snow'}
columns_name = {'Born': 'born', 'Age': 'age'}
# 注意:rename 修改之后,返回的是一个新的 DataFrame
scientists.rename(index=index_name, columns=columns_name)
使用
df.index和df.columns分别修改行标签和列标签
# 修改行标签
scientists.index = ['rosaline franklin', 'William Gosset', 'Florence Nightingale',
'Marie Curie', 'Rachel Carson', 'john snow', 'Alan Turing',
'Johann Gauss']
# 修改列标签
scientists.columns = ['born', 'Died', 'age', 'Occupation']
scientists
2.2.4 添加数据
行数据
添加行数据
修改行数据
scientists.loc[4] = ['Rachel Carson', '1907-5-27', '1964-4-14', 56, 'Biologist']
scientists
删除行数据
注意:删除行时,会返回新的 DataFrame。
scientists.drop([1, 3])
列数据
新增列/修改列
注意:添加列/修改列时,是直接对原始 DataFrame 进行修改
scientists['Country'] = ['England', 'England', 'England', 'French',
'America', 'England', 'England', 'Germany']
或
scientists.loc[:, 'Country'] = ['England', 'England', 'England', 'French',
'America', 'England', 'England', 'Germany']
scientists
删除列
注意:删除列时,会返回新的 DataFrame。
| 方式 | 说明 |
|---|---|
df.drop(['列标签', ...], axis=1) |
删除列标签对应的列数据,返回新的 DataFrame |
scientists.drop(['Country'], axis=1)
# 删除行
# drop返回新的的 DataFrame
scientists_dp=scientists.drop([1, 3])
# 索引恢复默认的序列 return回来
scientists_dp.reset_index().drop('列名'<如果没有就写index>,axis=1)
# 如果想要将index的元素列变为普通的列 只需要
xxx.reset_index()
quater_season_mapping = {1:'春',2:'夏',3:'秋',4:'冬'}
banks['Closing Season'] = banks['Closing Quarter'].replace(quater_season_mapping)
banks
2.2.5 条件查询
| 方式 | 说明 |
|---|---|
df.loc[条件...] |
获取 DataFrame 中满足条件的数据 |
df.query('条件...') |
获取 DataFrame 中满足条件的数据 |
注意:loc 和 query 中可以跟多个条件,可以使用 &(与)、|(或) 表示条件之间的关系。
scientists.loc[(scientists['Age'] > 60) & (scientists['Age'] < 80)]
或
scientists.loc[(scientists.Age > 60) & (scientists.Age < 80)]
scientists.query('Age > 60 & Age < 80')
分类聚合
| 方式 | 说明 |
|---|---|
df.groupby(列标签, ...).列标签.聚合函数() |
按指定列分组,并对分组 数据的相应列进行相应的 聚合操作 |
df.groupby(列标签, ...).agg({'列标签': '聚合', ...}) |
按指定列分组,并对分组 数据的相应列进行相应的 聚合操作 |
df.groupby(列标签, ...).aggregate({'列标签': '聚合', ...}) |
按指定列分组,并对分组 数据的相应列进行相应的 聚合操作 |
DataFrame排序

也可以直接df.sort_value(['列标签'])
Dataframe的运算
总结如下:DataFrame与DataFrame之间的运算,由于DataFrame中的每一元素都由其行列索引唯一确定,也就是说DataFrame中的每一元素都有一个(行索引,列索引)构成的坐标 。因此对于不同的DataFrame,只用索引匹配上的数据,对应元素相加,对于没有匹配上的数据,返回的是NaN值 。
—————————————————————————————
版权声明:本文为CSDN博主「数据分析与统计学之美」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_41261833/article/details/104176300
2.3 loc和iloc
对于loc

对于iloc
切片
china.loc[1999:2000,'country':'lifeExp'] # 名字
chian.iloc[1:3,2:4] #索引
2.4 Series
2.4.1 创建方式
传入一个Python列表
s = pd.Series(['banana', 42])
s = pd.Series(['banana', 'apple'])
s = pd.Series([50, 42])
通过 index 参数来指定行标签
s = pd.Series(['smart', 18], index=['name', 'age'])
print(s)
print(type(s))
2.4.2常用方法
| 方法 | 说明 |
|---|---|
s.mean() |
计算 Series 数据中元素的平均值 |
s.max() |
计算 Series 数据中元素的最大值 |
s.min() |
计算 Series 数据中元素的最小值 |
s.std() |
计算 Series 数据中元素的标准差 |
s.value_counts() |
统计 Series 数据中不同元素的个数 |
s.count() |
统计 Series 数据中非空(NaN)元素的个数 |
s.describe() |
显示 Series 数据中元素的各种统计值 |
| 方法 | 说明 |
|---|---|
| append | 连接两个或多个Series |
| corr | 计算与另一个Series的相关系数 |
| cov | 计算与另一个Series的协方差 |
| describe | 计算常见统计量 |
| drop_duplicates | 返回去重之后的Series |
| equals | 判断两个Series是否相同 |
| get_values | 获取Series的值,作用与values属性相同 |
| hist | 绘制直方图 |
| isin | Series中是否包含某些值 |
| min | 返回最小值 |
| max | 返回最大值 |
| mean | 返回算术平均值 |
| median | 返回中位数 |
| mode | 返回众数 |
| quantile | 返回指定位置的分位数 |
| replace | 用指定值代替Series中的值 |
| sample | 返回Series的随机采样值 |
| sort_values | 对值进行排序 |
| to_frame | 把Series转换为DataFrame |
| unique | 去重返回数组 |
2.4.3 bool索引
age_series[age_series>age_series.mean()]
2.5 数据组合concat和merge
| 方法 | 说明 |
|---|---|
pd.concat([df1, df2, ..]) |
多个数据集(DataFrame或Series)之间按行标签索引 或列标签索引拼接,默认是outer,可以设置为inner |
# ignore_index=True:表示 concat 拼接时忽略索引
pd.concat([df1, df2, df3], ignore_index=True)
DataFrame和DataFrame 进行拼接:
1)将 df1、df2和 df3 按照行标签对齐,进行列拼接
pd.concat([df1, df2, df3], axis=1)
concat 方法的 join参数:
- 默认为 outter:无法对齐的行/列,默认在拼接后的数据中会填充为 NaN,因为默认拼接是 outter 拼接
- 设置为 inner:只有能够对齐的行/列,才会出现在拼接的结果中
将 df1 和 df3 按列标签对齐,进行行拼接,设置 join='inner'
pd.concat([df1, df3], join='inner')

merge 方法类似于 sql 中的 join 语句,用于两个数据集之间按照行标签索引|列标签索引链接,默认是inner,可以设置为:left、right、outer
基本格式:
| 方法 | 说明 |
|---|---|
pd.merge(left, right, ...) 或 left.merge(right, ...) |
两个数据集直接进行关联操作 |
merge函数的参数:
- left:左侧数据集
- right:右侧数据集
- how:关联方式,默认为 inner,可以设置为:left、right、outer
- on='列名': 左侧和有则数据以哪一列进行关联操作,左右两侧列名相同时才指定 on 参数
- left_on='左侧列名' 和 right_on='右侧列名':左右两侧关联时,列名不同时使用
- left_index=False:默认为 False,设置为 True,表示左侧的行标签和右侧的数据进行关联
- right_index=False:默认为 False,设置为 True,表示左侧的数据和右侧的行标签进行关联
sqlite是一个微型的、本地的数据库,不必像mysql需要额外启动运行,依靠其特殊的文件,用来存储数据,并提供和数据文件交互的方法;或者称sqlite为本地数据文件系统更为贴切。
# 部分版本的anaconda没有sqlalchemy模块,需要额外单独安装:pip install sqlalchemy
from sqlalchemy import create_engine
# 创建数据库连接对象,并指定数据文件路径
engine = create_engine('sqlite:///data/chinook.db')
# 加载其中的 tracks 数据表的数据
tracks = pd.read_sql_table('tracks', engine)
# 查看前 5 个数据
tracks.head()
tracks_sub = tracks[['TrackId', 'GenreId', 'Milliseconds']]
genres_track = pd.merge(genres, tracks_sub, on='GenreId', how='left')
或
genres_track = genres.merge(tracks_sub, on='GenreId', how='left')
genres_track
# 将 genre_time 数据从 ms 转换为时间单位,保留到 s,并按时间从高到低排序
pd.to_timedelta(genre_time, unit='ms').dt.floor('s').sort_values(ascending=False)
join 方法类是 merge 方法的一个特殊情况,被调用的数据集按照行标签索引|列标签索引和另一个数据集的行标签索引关联,默认是left,可以设置为:right,inner、outer
基本格式:
| 方法 | 说明 |
|---|---|
df.join(other, ...) |
左侧数据集的行标签或列标签和右侧数据集的行标签进行关联操作 |
join函数的参数:
- other:右侧数据集
- how:关联方式,默认为 left,可以设置为:right、inner、outer
- on='左侧行标签或列标签': 左侧数据集的行标签名称或列标签名称,on省略时,默认为左侧数据行标签
- lsuffix:关联后的数据中出现相同列名时,lsuffix指定左侧数据集出现相同列名的后缀
- rsuffix:关联后的数据中出现相同列名时,rsuffix指定右侧数据集出现相同列名的后缀
# 示例:stock_2016 和 stock_2017 按照行标签进行管理,设置为 outter 连接
stock_2016.join(stock_2017, lsuffix='2016', rsuffix='2017', how='outer')
2.6缺失值的处理
注意点1:缺失值和其它类型的数据不同,它毫无意义,NaN不等于0,也不等于空字符串
print(np.NaN==True)
print(np.NaN==False)
print(np.NaN==0)
print(np.NaN=='')
print(np.NaN==None)
# 都为False
注意点2:两个NaN也不相等
print(np.NaN==np.NaN)
print(np.NaN==np.nan)
print(np.NaN==np.NAN)
print(np.NAN==np.nan)
# 都为False
pandas 判断是否为缺失值方法:
| 方法 | 说明 |
|---|---|
pd.isnull(obj) 或 pd.isna(obj) |
判断 obj 是否为缺失值 |
print(pd.isnull(np.NaN))
print(pd.isnull(np.nan))
print(pd.isnull(np.NAN))
print(pd.notnull(42))
# 都为True
加载缺失值数据
# na_values=["DR-3"]:加载数据时,把 'DR-3' 当做缺失值
pd.read_csv('./data/survey_visited.csv', na_values=["DR-3"], keep_default_na=False)

缺失值处理方式概述
2)比如此时我们想查看泰坦尼克号上获救与否的人数统计
train['Survived'].value_counts()

构造缺失值统计的函数
def missing_values_table(df):
# 计算所有的缺失值c
mis_val = df.isnull().sum()
# 计算缺失值的比例
mis_val_percent = 100 * mis_val / len(df)
# 将结果拼接成 DataFrame
mis_val_table = pd.concat([mis_val, mis_val_percent], axis=1)
# 将列重命名
mis_val_table_ren_columns = mis_val_table.rename(columns={0: '缺失值', 1: '占比(%)'})
# 将缺失值为0的列去除,并按照缺失值占比进行排序
mis_val_table_ren_columns = mis_val_table_ren_columns[mis_val_table_ren_columns.iloc[:, 1]!=0].sort_values(
'占比(%)', ascending=False)
# 打印信息
print(f'传入的数据集共{df.shape[1]}列,\n其中{mis_val_table_ren_columns.shape[0]}列有缺失值')
return mis_val_table_ren_columns
# 查看缺失值情况
missing_values_table(train)

缺失值可视化
import missingno as msno
msno.bar(train)
missingno.matrix 函数 提供了快速直观的查看缺失值的分布情况:
# 查看缺失值分布
msno.matrix(train)
# 随机从 train 数据中取出 100 条数据,查看缺失值分布情况
msno.matrix(train.sample(100))
# 热力图
msno.heatmap(train)
删除缺失值
删除缺失值:删除缺失值会损失信息,并不推荐删除,当缺失数据占比较低的时候,可以尝试使用删除缺失值
1)按行删除:删除指定列为缺失值的行记录
# 复制一份数据
train_cp = train.copy()
# 对Age列进行处理,空值就删除整行数据
train_cp.dropna(subset=['Age'], how='any', inplace=True)
# 输出Age列缺失值的总数
print(train_cp['Age'].isnull().sum())
# 图形化缺失值情况
msno.matrix(train_cp)
补充内容:dropna的参数
df.dropna(axis=0, how='any', thresh=None, subset=None, inplace=False)
参数说明:
* 可选参数subset:不与thresh参数一起使用:接收一个列表,列表中的元素为列名: 对特定的列进行缺失值删除处理
* 可选参数thresh:参数为int类型,按行去除NaN值,去除NaN值后该行剩余数值的数量(列数)大于等于n,便保留这一行
* 可选参数axis:默认为0,设置为 0 或 'index' 表示按行删除,设置为 1 或 'columns' 表示按列删除
* 可选参数how:默认为'any',表示如果存在NA值,则删除该行或列,设置为'all',表示所有值都是NA,则删除该行或列
* 可选参数inplace:表示是否修改变原始的数据集,默认为False,可以设置为True
2)按列删除:当一列包含了很多缺失值的时候(比如超过80%),可以使用df.drop(['列名',..], axis=1)函数将指定列删除,但最好不要删除数据
# 复制一份数据
train_cp = train.copy()
# 对Age列进行处理,空值就删除整行数据
train_cp.drop(['Age'], axis=1, inplace=True)
# 图形化缺失值情况
msno.matrix(train_cp)
注意:Age 列没有了!!!
填充缺失值
填充缺失值(非时间序列数据):填充缺失值是指用一个估算的值来去替代缺失值
1)使用常量来替换(默认值)
# 复制一份数据
train_constant = train.copy()
# 计算各列空值总数
print('填充缺失值之前:')
print(train_constant.isnull().sum())
# 将空值都填为0,inplace=True为必要参数
train_constant.fillna(0, inplace=True)
# 计算各列空值总数
print('填充缺失值之后:')
print(train_constant.isnull().sum())
2)使用统计量替换(缺失值所处列的平均值、中位数、众数)
# 复制一份数据
train_mean = train.copy()
# 计算年龄的平均值
age_mean = train_mean['Age'].mean()
print(age_mean)
# 使用年龄的平均值填充 Age 列的缺失值
train_mean['Age'].fillna(age_mean, inplace=True)
train_mean.isnull().sum()
时序数据缺失值处理
时序数据在某一列值的变化往往有一定线性规律,绝大多数的时序数据,具体的列值随着时间的变化而变化,所以对于有时序的行数据缺失值处理有三种方式:
- 用时间序列中空值的上一个非空值填充
- 用时间序列中空值的下一个非空值填充
- 线性插值方法
1)加载样例时序数据集 city_day.csv,该数据集为印度城市空气质量数据(2015-2020)
city_day = pd.read_csv('./data/city_day.csv', parse_dates=True, index_col='Date')
# 复制一份数据
city_day_cp = city_day.copy()
# 查看数据的前 5 行
city_day_cp.head()
2)用之前封装的方法(本章3.2.2小节),查看数据缺失情况:
city_day_missing = missing_values_table(city_day_cp)
city_day_missing
3)使用fillna函数中的ffill参数,用时间序列中空值的上一个非空值填充
# 截取一小部分数据用于填充效果查看
city_day['Xylene'][50:64]
# 填充缺失值
city_day.fillna(method='ffill', inplace=True)
# 截取一小部分数据查看填充效果
city_day['Xylene'][50:64]
4)上面填充了缺失值之后,再次查看缺失值情况
# 查看缺失值比例
missing_values_table(city_day)
5)使用fillna函数中的bfill参数,用时间序列中空值的下一个非空值填充
# 截取一小部分数据用于填充效果查看
city_day['AQI'][20:30]
6)上面填充了缺失值之后,再次查看缺失值情况
# 查看缺失值比例
missing_values_table(city_day)
7)使用df.interpolate(limit_direction="both", inplace=True) 对缺失数据进行线性填充
- 绝大多数的时序数据,具体的列值随着时间的变化而变化。 因此,使用bfill和ffill进行插补并不是解决缺失值问题的最优方案。
- 线性插值法是一种插补缺失值技术,它假定数据点之间存在严格的线性关系,并利用相邻数据点中的非缺失值来计算缺失数据点的值
# 截取一小部分数据用于填充效果查看
city_day_cp['Xylene'][50:65]
# 线性插值填充
city_day_cp.interpolate(limit_direction='both', inplace=True)
# 截取一小部分数据用于查看填充效果
city_day_cp['Xylene'][50:65]
2.7 apply自定义函数
def my_sq(x):
"""求平方"""
return x ** 2
# 注意:series.apply(函数名)
df['a'].apply(my_sq)
def my_add(x, n):
"""求和"""
return x + n
# 注意:args 参数必须是一个元组,这里 3 是传递给 n 的
df['a'].apply(my_add, args=(3,))

3. DataFrame 的 apply 方法
DataFrame 的 apply 函数用法和 Series的用法基本一致,当传入一个函数后,apply 方法就会把传入的函数应用于 DataFrame 的行或列
3.1 按列执行
1)首先定义一个处理函数
def sub_one(x):
"""减1操作"""
print(x)
return x - 1
2)针对 df 进行 apply 操作,默认按列执行
# 按列计算
df.apply(sub_one)
按行执行
DataFrame 的 apply 函数有一个
axis参数,默认值为 0,表示按列执行;可以设置为axis=1,表示按行执行
1)针对 df 进行 apply 操作,设置按行执行
apply自定义函数
学习目标
- 掌握 apply 和 applymap 的用法
- 知道如何创建向量化函数
- 知道 lambda 表达式的好处
1. apply 函数简介
pandas 的 apply() 函数可以作用于 Series 或者整个 DataFrame,功能也是自动遍历整个 Series 或者 DataFrame,对每一个元素运行指定的函数。
1)pandas 提供了很多数据处理的 API,但当提供的 API 不能满足需求的时候,需要自己编写数据处理函数, 这个时候可以使用 apply 函数
2)apply 函数可以接收一个自定义函数,可以将 DataFrame 的行或列数据传递给自定义函数处理
3)apply 函数类似于编写一个 for 循环,遍历行、列的每一个元素, 但比使用 for 循环效率高很多
2. Series 的 apply 方法
Series 有一个 apply 方法,该方法有一个 func 参数,当传入一个函数后,apply 方法就会把传入的函数应用于Series 的每个元素.
1)创建一个 DataFrame 数据集,准备数据
df = pd.DataFrame({'a': [10, 20, 30], 'b': [20, 30, 40]})
df

2)创建一个自定义函数
def my_sq(x):
"""求平方"""
return x ** 2
3)使用 apply 方法进行数据处理
# 注意:series.apply(函数名)
df['a'].apply(my_sq)

4)series 的 apply 还可以接收多个参数
def my_add(x, n):
"""求和"""
return x + n
# 注意:args 参数必须是一个元组,这里 3 是传递给 n 的
df['a'].apply(my_add, args=(3,))

# 使用 apply 时,也可直接指定参数 n 的值
df['a'].apply(my_add, n=3)

3. DataFrame 的 apply 方法
DataFrame 的 apply 函数用法和 Series的用法基本一致,当传入一个函数后,apply 方法就会把传入的函数应用于 DataFrame 的行或列
3.1 按列执行
1)首先定义一个处理函数
def sub_one(x):
"""减1操作"""
print(x)
return x - 1
2)针对 df 进行 apply 操作,默认按列执行
# 按列计算
df.apply(sub_one)
3.2 按行执行
DataFrame 的 apply 函数有一个
axis参数,默认值为 0,表示按列执行;可以设置为axis=1,表示按行执行
1)针对 df 进行 apply 操作,设置按行执行
# 按行计算
df.apply(sub_one, axis=1)
3.3 每一个值都执行
# 按行计算
df.apply(sub_one, axis=1)
DataFrame 还有一个 applymap 函数,applymap 也有一个 func 参数接收一个函数,针对 DataFrame 每个值应用 func 指定的函数进行操作,分别返回的结果构成新的 DataFrame 对象
注意:applymap函数是 DataFrame 独有的,Series 没有这个方法
# sub_one 应用于 df 中的每个元素
df.applymap(sub_one)
在声明函数时,使用装饰器@np.vectorize,将函数向量化
import numpy as np
# 函数向量化
@np.vectorize
def add_vec_2(x, y):
if x != 0:
return x + y
else:
return x
add_vec_2(df['a'], df['b'])
分组操作
在 SQL 中我们经常使用 GROUP BY 将某个字段,按不同的取值进行分组,在 pandas 中也有 groupby 函数;
分组之后,每组都会有至少1条数据,将这些数据进一步处理返回单个值的过程就是聚合。
比如:分组之后计算算术平均值,或者分组之后计算频数,都属于聚合。
基本格式:
| 方式 | 说明 |
|---|---|
方式1: df.groupby(列标签, ...).列标签.聚合函数() |
按指定列分组,并对分组数据 的相应列进行相应的 聚合操作 |
方式2: df.groupby(列标签, ...).agg({'列标签': '聚合', ...}) df.groupby(列标签, ...).列表签.agg(聚合...) |
按指定列分组,并对分组数据 的相应列进行相应的 聚合操作 |
方式3: df.groupby(列标签, ...).aggregate({'列标签': '聚合', ...}) df.groupby(列标签, ...).列表签.aggregate(聚合...) |
按指定列分组,并对分组数据 的相应列进行相应的聚合操作 |
注意:
1)方式1 只能使用 pandas 内置的聚合方法,并且只能进行一种聚合
2)方式2 和 方式3 除了能够使用 pandas 内置的聚合方法,还可以使用其他聚合方法,并且可以进行多种聚合
2 pandas 内置的聚合方法
可以与groupby一起使用的方法和函数:
| pandas方法 | Numpy函数 | 说明 |
|---|---|---|
| count | np.count_nonzero | 频率统计(不包含NaN值) |
| size | 频率统计(包含NaN值) | |
| mean | np.mean | 求平均值 |
| std | np.std | 标准差 |
| min | np.min | 最小值 |
| quantile() | np.percentile() | 分位数 |
| max | np.max | 求最大值 |
| sum | np.sum | 求和 |
| var | np.var | 方差 |
| describe | 计数、平均值、标准差,最小值、分位数、最大值 | |
| first | 返回第一行 | |
| last | 返回最后一行 | |
| nth | 返回第N行(Python从0开始计数) |
1.3 分组聚合操作演示
1)加载 gapminder.tsv 数据集
gapminder = pd.read_csv('./data/gapminder.tsv', sep='\t')
gapminder.head()

2 )示例:计算每年期望年龄的平均值
# 示例:计算每年期望年龄的平均值
# gapminder.groupby('year')['lifeExp'].mean()
gapminder.groupby('year').lifeExp.mean()
或
gapminder.groupby('year').agg({'lifeExp': 'mean'})
或
import numpy as np
gapminder.groupby('year').agg({'lifeExp': np.mean})



transform 转换
- transform 转换,需要把 DataFrame 中的值传递给一个函数, 而后由该函数"转换"数据
- aggregate(聚合) 返回单个聚合值,但 transform 不会减少数据量
2.1 transform 功能演示
需求:按年分组,并计算组内每个人的预期寿命和该组平均年龄的差值
def lifeExp_diff(x):
return x - x.mean()
# gapminder.groupby('year')['lifeExp'].transform(lifeExp_diff)
gapminder.groupby('year').lifeExp.transform(lifeExp_diff)

2 transform 分组填充缺失值
之前介绍了填充缺失值的各种方法,对于某些数据集,可以使用列的平均值来填充缺失值。某些情况下,可以考虑将列进行分组,分组之后取平均再填充缺失值
1)加载 tips.csv 数据集,并从其中随机取出 10 条数据
tips_10 = pd.read_csv('./data/tips.csv').sample(10, random_state=42)
tips_10
2)构建缺失值
import numpy as np
tips_10.iloc[[1, 3, 5, 7], 0] = np.nan
tips_10

3)分组查看缺失情况
tips_10.groupby('sex').count()

4.1 分组操作
1)准备数据,加载 tips.csv 数据集,随机取出其中的 10 条数据
tips_10 = pd.read_csv('./data/tips.csv').sample(10, random_state=42)
tips_10

2)调用 groupby 方法,创建分组对象
sex_groups = tips_10.groupby('sex')
sex_groups

结果说明:上面返回的结果是 DataFrame 的索引,实际上就是原始数据的行数
3)在 DataFrameGroupBy 对象基础上,直接就可以进行 aggregate、transform 等计算
sex_groups.mean("index") # 有bug 需要随机填一个参数进去

结果说明:上面结果直接计算了按 sex 分组后,所有列的平均值,但只返回了数值列的结果,非数值列不会计算平均值
4)通过 get_group 方法选择分组
sex_groups.get_group('Female')

4.2 遍历分组
通过 DataFrameGroupBy 对象,可以遍历所有分组,相比于在 groupby 之后使用aggregate、transform和filter,有时候使用 for 循环解决问题更简单:
for sex_group in sex_groups:
print(type(sex_group))
print(sex_group)
注意:DataFrameGroupBy对象不支持下标取值,会报错
# 这句代码会出错
sex_groups[0]
4.3 多个分组
前面使用的 groupby 语句只包含一个变量,可以在 groupby 中添加多个变量
比如上面用到的 tips.csv 数据集,可以使用groupby按性别和用餐时间分别计算小费数据的平均值:
group_avg = tips_10.groupby(['sex', 'time']).mean()
group_avg
也可以在分组的时候通过as_index=False参数(默认是True),效果与调用reset_index()一样
# as_index=False:分组字段不作为结果中的行标签索引
tips.groupby(['sex', 'time'], as_index=False).mean()

浙公网安备 33010602011771号