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报错

image-20240105155033017 image-20240105155055148 image-20240105155104230

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
image-20240106162524755

使用colums参数指定列的顺序

image-20240106162609966

使用 index 参数来指定行标签

image-20240106162657091

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_])

image-20240106162938009

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)
image-20240113093602931

使用 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 添加数据

行数据

添加行数据

image-20240106164813509

修改行数据

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()

image-20240113093702546
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)]
image-20240106171705442
scientists.query('Age > 60 & Age < 80')
image-20240106171712602

分类聚合

方式 说明
df.groupby(列标签, ...).列标签.聚合函数() 按指定列分组,并对分组 数据的相应列进行相应的 聚合操作
df.groupby(列标签, ...).agg({'列标签': '聚合', ...}) 按指定列分组,并对分组 数据的相应列进行相应的 聚合操作
df.groupby(列标签, ...).aggregate({'列标签': '聚合', ...}) 按指定列分组,并对分组 数据的相应列进行相应的 聚合操作
image-20240106171754875 image-20240106171833846

DataFrame排序

image-20240106172227075

也可以直接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

​ image-20240106161728159

对于iloc

image-20240106161843036

切片

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])

image-20240106162106385

通过 index 参数来指定行标签

s = pd.Series(['smart', 18], index=['name', 'age'])
print(s)
print(type(s))
image-20240106162203904

2.4.2常用方法

image-20240106162230349
方法 说明
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()]
image-20240106162412440

2.5 数据组合concat和merge

​

方法 说明
pd.concat([df1, df2, ..]) 多个数据集(DataFrame或Series)之间按行标签索引 或列标签索引拼接,默认是outer,可以设置为inner
# ignore_index=True:表示 concat 拼接时忽略索引
pd.concat([df1, df2, df3], ignore_index=True)
image-20240108162511724

DataFrame和DataFrame 进行拼接:

1)将 df1、df2和 df3 按照行标签对齐,进行列拼接

pd.concat([df1, df2, df3], axis=1)
image-20240108162713481

concat 方法的 join参数:

  • 默认为 outter:无法对齐的行/列,默认在拼接后的数据中会填充为 NaN,因为默认拼接是 outter 拼接
  • 设置为 inner:只有能够对齐的行/列,才会出现在拼接的结果中
image-20240108162901786

将 df1 和 df3 按列标签对齐,进行行拼接,设置 join='inner'

pd.concat([df1, df3], join='inner')

img

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
img
# 将 genre_time 数据从 ms 转换为时间单位,保留到 s,并按时间从高到低排序
pd.to_timedelta(genre_time, unit='ms').dt.floor('s').sort_values(ascending=False)
img

join 方法类是 merge 方法的一个特殊情况,被调用的数据集按照行标签索引|列标签索引和另一个数据集的行标签索引关联,默认是left,可以设置为:right,inner、outer

基本格式:

方法 说明
df.join(other, ...) 左侧数据集的行标签或列标签和右侧数据集的行标签进行关联操作

join函数的参数:

  • other:右侧数据集
  • how:关联方式,默认为 left,可以设置为:right、inner、outer
  • on='左侧行标签或列标签': 左侧数据集的行标签名称或列标签名称,on省略时,默认为左侧数据行标签
  • lsuffix:关联后的数据中出现相同列名时,lsuffix指定左侧数据集出现相同列名的后缀
  • rsuffix:关联后的数据中出现相同列名时,rsuffix指定右侧数据集出现相同列名的后缀
img
# 示例:stock_2016 和 stock_2017 按照行标签进行管理,设置为 outter 连接
stock_2016.join(stock_2017, lsuffix='2016', rsuffix='2017', how='outer')
img

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)

img

缺失值处理方式概述

2)比如此时我们想查看泰坦尼克号上获救与否的人数统计

train['Survived'].value_counts()

img

构造缺失值统计的函数

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)

img

缺失值可视化
import missingno as msno
msno.bar(train)
img

missingno.matrix 函数 提供了快速直观的查看缺失值的分布情况:

# 查看缺失值分布
msno.matrix(train)
img
# 随机从 train 数据中取出 100 条数据,查看缺失值分布情况
msno.matrix(train.sample(100))
# 热力图
msno.heatmap(train)
img
删除缺失值

删除缺失值:删除缺失值会损失信息,并不推荐删除,当缺失数据占比较低的时候,可以尝试使用删除缺失值

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)
img

补充内容: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)
img

注意: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()
img

2)用之前封装的方法(本章3.2.2小节),查看数据缺失情况:

city_day_missing = missing_values_table(city_day_cp)
city_day_missing
img

3)使用fillna函数中的ffill参数,用时间序列中空值的上一个非空值填充

# 截取一小部分数据用于填充效果查看
city_day['Xylene'][50:64]
img
# 填充缺失值
city_day.fillna(method='ffill', inplace=True)
# 截取一小部分数据查看填充效果
city_day['Xylene'][50:64]
img

4)上面填充了缺失值之后,再次查看缺失值情况

# 查看缺失值比例
missing_values_table(city_day)
img

5)使用fillna函数中的bfill参数,用时间序列中空值的下一个非空值填充

# 截取一小部分数据用于填充效果查看
city_day['AQI'][20:30]
img img

6)上面填充了缺失值之后,再次查看缺失值情况

# 查看缺失值比例
missing_values_table(city_day)
img

7)使用df.interpolate(limit_direction="both", inplace=True) 对缺失数据进行线性填充

  • 绝大多数的时序数据,具体的列值随着时间的变化而变化。 因此,使用bfill和ffill进行插补并不是解决缺失值问题的最优方案。
  • 线性插值法是一种插补缺失值技术,它假定数据点之间存在严格的线性关系,并利用相邻数据点中的非缺失值来计算缺失数据点的值
# 截取一小部分数据用于填充效果查看
city_day_cp['Xylene'][50:65]
img
# 线性插值填充
city_day_cp.interpolate(limit_direction='both', inplace=True)
# 截取一小部分数据用于查看填充效果
city_day_cp['Xylene'][50:65]
img

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,))

image-20240109161730189

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

img

2)创建一个自定义函数

def my_sq(x):
    """求平方"""
    return x ** 2

3)使用 apply 方法进行数据处理

# 注意:series.apply(函数名)
df['a'].apply(my_sq)

img

4)series 的 apply 还可以接收多个参数

def my_add(x, n):
    """求和"""
    return x + n

# 注意:args 参数必须是一个元组,这里 3 是传递给 n 的
df['a'].apply(my_add, args=(3,))

img

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

img

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()

img

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})

img

img

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)

img

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

img

3)分组查看缺失情况

tips_10.groupby('sex').count()

img

4.1 分组操作

1)准备数据,加载 tips.csv 数据集,随机取出其中的 10 条数据

tips_10 = pd.read_csv('./data/tips.csv').sample(10, random_state=42)
tips_10

img

2)调用 groupby 方法,创建分组对象

sex_groups = tips_10.groupby('sex')
sex_groups

img

结果说明:上面返回的结果是 DataFrame 的索引,实际上就是原始数据的行数

3)在 DataFrameGroupBy 对象基础上,直接就可以进行 aggregate、transform 等计算

sex_groups.mean("index") # 有bug 需要随机填一个参数进去 

img

结果说明:上面结果直接计算了按 sex 分组后,所有列的平均值,但只返回了数值列的结果,非数值列不会计算平均值

4)通过 get_group 方法选择分组

sex_groups.get_group('Female')

img

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()
posted @ 2024-01-13 09:48  Object_gl  阅读(154)  评论(0)    收藏  举报