本文章参考网络视频以及菜鸟教程等内容进行Pandas核心内容的梳理,包含大部分当前最常用的一些功能,帮助快速入门或复习Pandas。
- 基础操作
- 对象创建和数据查看
- 实际工作常用命令
- 常用工作流
- 字符串、时间信息的处理
- 表格的排序和拼接
- 长表格转宽表格
- 注意事项
Pandas,python+data+analysis的组合缩写,是python中基于numpy和matplotlib的第三方数据分析库,与后两者共同构成了python数据分析的基础工具包,广泛应用在学术、金融、统计学等各个数据分析领域。
① Series:类似表格中的一个列(column),类似于一维数组,可以保存任何数据类型。由索引(index)和列组成
② Dataframe:表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔型值)。Dataframe 既有行索引也有列索引,它可以被看做由多个 Series 组成的字典(共同用一个索引)。
pandas.Series( data, index, dtype, name, copy):创建一个对象
- :一组数据(ndarray)
- :数据索引标签,默认为0
- :数据类型,默认自动判断
- :设置名称
- :拷贝数据,默认为False
① 由列表创建Series
创建时不指定索引和名称
默认索引为RangeIndex,也就是 0,1,2,⋯0, 1, 2,cdots0,1,2,⋯
创建时指定索引(行索引)和名称(每行的名称,在表格中作为列索引或行索引)
② 由字典创建Series
由列表创建需要指定行索引或名称,由字典创建若已在字典中指定过行索引了,在创建Series中再次指定为在其中的索引中进行选择,若在方法中指定在字典中不存在的索引,将会为空值.
③ Series序列三大属性:,,
- :前面提到过,就是该序列的名称,组装成Dataframe后会成为表格的column或index(下面会介绍)
- :Series序列中的所有值
- :Series序列的索引值
pandas.Dataframe(data, index, columns, dtype, copy):构造方法
- :一组数据(, , , , 等类型)
- :索引值 / 行标签
- :列标签
- :数据类型
- :拷贝数据,默认为False
如果参数 和 未指定,默认为 RangeIndex(0, 1, 2,…, n),也就是 0,1,2,⋯0,1,2,cdots0,1,2,⋯
① 利用Python列表创建Dataframe对象
利用这种形式创建的表格,默认是按列的,每个子列表的第一个元素构成表格中的每列()
② 利用Python字典创建Dataframe对象
传入一个字典,根据字典创建表格(Dataframe)对象;字典中的为表格中的名称,也就是列索引,每行默认是列表中对应元素的索引,也就是行索引.
③ 利用Series对象创建Dataframe对象
④ 在字典中指定每行的行索引创建Dataframe对象
也可以指定行索引,在指定行索引时,默认按字典中第一个元素的行索引顺序,例如上方案例中’duration’列和列元素中的顺序和第一列中元素顺序相同.
⑤ 在字典中不指定行索引,创建对象时指定行索引
指定行索引中按顺序与原来索引对应,超出数量的索引也会创建,但元素用空值’NaN’替代
:Not a Number,表示空值.
⑥ 在字典中指定行列索引后,创建对象时选择指定行列索引
若选中未指定的索引,则该列或该行的值为空值
⑦ 将Dataframe表格转换回Python字典
Dataframe对象利用方法即可转换回python字典,但是对应字典是上述形式,即字典中的也是字典,该字典的为Dataframe中的行索引,为值.
① 访问整个列索引()或行索引()
访问Dataframe的索引相关属性,方法可转换成中的对象.
② 更改Dataframe表格对象的索引
直接对Dataframe对象的属性和赋值可以更改整个行索引或列索引.
更改部分索引时,也可以单独指定参数或参数,若不指定则不更改.
① 选择表格中的列与行 ()
- 若使用一个且是切片操作,仅支持行索引名称切片或行索引数字切片.
- 若使用一个且内嵌一个,则表示选择列索引,但不支持列索引切片和数字切片操作.
- 若使用一个且非切片操作,则第一个表示选择列索引.
- 注:列索引不能切片或用数字表示,行索引可以切片或用数字表示,且切片操作若为标签切片的话包含最后一个数据,若为整数切片则不含最后一个数据。
② 选择表格中的列与行 (, )
③ 、、之间的区别:
三种方法都能用布尔值来表示索引,如下所示
、之间的区别:
- 函数:基于行标签和列标签进行索引的,切片时包含最后一个数据,不能对columns直接使用整数索引.
- 函数:基于行和列的位置进行索引的,索引值从0开始,并且切片时不包含最后一个数据, i表示integer,对于index和columns,只能用整数来索引.
与之间的一些区别:
- 在一个中括号中只能填一次,不能用逗号间隔一次同时做选择行和列操作
- 中若非切片操作,则其中为列索引,而另外两种方法中的第一组值都为行索引.
Pandas中也有一些其它的数据选择操作,但不常用也不推荐使用,这三种方法已经基本可以满足需求了.
④ 过滤数据
过滤数据:
⑤ 如果访问单个值的话也可以用
该方法与上方的三种方法的不同时,得到的数据是该元素的数据类型,而上方的方法返回的都是或类型.
① 读取excel文件(、)
pd.read_excel(path):读取excel文件
- path:要读取的文件路径
- sheetname:指定读取excel中哪一个工作表,默认sheetname = 0,即默认读取excel中的第一个工作表
- 若sheetname = ‘sheet1’,即读取excel中的sheet1工作表;
- 若sheetname = ‘汇总’,即读取excel中命名为"汇总"的工作表;
- header:用作列名的行号,默认为header = 0
- 若header = None,则表明数据中没有列名行;
- 若header = 0,则表明第一行为列名;
- names:列名命名或重命名,默认不变
② 读取csv文件
pd.read_csv(path):读取csv文件
- path:要读取的文件路径
- sep:指定列与列间的分隔符,默认sep = ‘,’
- 若sep = ‘ ’,即列与列间用制表符 分隔;
- 若sep = ‘,’,即列与列间用逗号分隔;
- header:用作列名的行号,默认为0
- 若header = None,则表明数据中没有列名行;
- 若header = 0,则表明第一行为列名;
- names:列名命名或重命名,默认不变
- encoding:指定用于unicode文本编码格式
- 若encoding = ‘utf-8’,则表明用UTF-8编码的文本;
- 若encoding = ‘gbk’,则表明用gbk编码的文本;
③ 读取txt文件
pandas中的即可以读取csv文件,也可以读取txt文件方法同上,也可以用读取txt文件,区别在于sep的默认参数不同.
pd.read_table()
- path:要读取的文件绝对路径
- sep:指定列与列间的分隔符,默认sep = ‘ ’
- 若sep = ‘ ’,即列与列间用制表符 分隔;
- 若sep = ‘,’,即列与列间用逗号,分隔;
- header:用作列名的行号,默认为header = 0
- 若header = None,则表明数据中没有列名行;
- 若header = 0,则表明第一行为列名;
- names:列名命名或重命名,默认不变
④ 读取JSON文件
pd.read_json(path)
- :文件路径
- :加载不同的数据封装格式,常用 ,,
:多个字典组成的列表
-
json文件结构案例:
-
读取后:
:key作为行索引
-
json文件结构案例:
-
读取后:
:key作为列索引
-
json文件结构案例:
-
读取后:
这里介绍这四种文件的读取操作,基本满足大多情况
创建Dataframe表格
① 数据基本信息预览:.head(n) / .tail(n) / .sample(n)
- :打印前n行数据,默认n为5
- :打印后n行数据,默认n为5
- :打印随机n行数据,默认n为5
② 表格基本信息预览:.shape() / .len() / .dtypes() / .describe() /.info()
- :打印表格形状,(行数,列数)
- :打印表格长度(行数)
- :打印表格中的行索引和该Series的元素数据类型,返回一个Series
- :打印数值类型数据基本统计信息,包括:
- :元素数量
- :平均数
- :标准差
- :最小值
- :四分位数
- :最大值
- :表格基本信息,包括:
- 数据结构、行/列索引数,每个Series的数据类型,所占内存等
③ 统计性信息操作:.unique() / .nunique() / .groupby() / .agg() /.apply()
- :返回一个由Series中唯一的元素组成的列表 (ps:Dataframe对象没这个方法)
- :返回唯一值元素的个数(Series和Dataframe对象都能用,后者返回的是其中所有Series和其对应的唯一值数量,可以进一步利用求和)
- :根据某个(多个)字段划分为不同的组(group)
- :用于将某个函数应用于表格中的每个Series或Series中的每个值
- :对数据计算统计信息,一般在之后使用
/ :唯一值 / 唯一值个数
:分组,返回一个对象,直接打印为其内存地址 (可以转为list进行查看)
一般会在执行分组后进行其它操作,下面会讲解
例:过程拆解:
可以看出,由于workout中的calories中四个元素都不同,按calories分组也就意味着按每个元素单独分为一组,用转为list之后数据来说明,每个分组为一个元组,每个元组中第一个元素为分类依据的元素,后面几个元素为数据的columns标签,然后开始为每一条分组数据的行索引和数据。
计算统计信息:
函数经常在函数之后使用,也就是对数据分组后进行统计信息计算
这里的数据集以泰坦尼克号中的训练集为例
percentile:百分数,quantile:量值;就是返回数据中的四分位数
函数处理后的数据为Dataframe对象,案例中的行和列都是多级的索引
.apply(func, axis=0, raw=False)
- :传入的函数或Lambda表达式
- :默认为0(列),0或index(列)1或columns(行)
- :默认为False,False ,表示把每一行或列作为 Series 传入函数中;True,表示接受的是 ndarray 数据类型
处理的若为Series,则为每个元素应用函数func
① .set_index():将某一列设置为index
- :需要设置为index的列名
- :布尔值,在将原来的列设置为index,是否需要删除原来的列,默认为True
- :布尔值,新的index设置之后,是否要删除原来的index,默认为True
- :布尔值,是否进行原地操作,即是否要用新的Dataframe取代原来的Dataframe,默认False
不保留(左),保留(右)
当表格中含有多个行索引时,对于该表格,只能使用最外层行索引确定,确定后可以进一步使用内层行索引确认
② reset_index():重新设置表格的行索引
- :布尔值,表示是否舍弃当前行索引,默认为False
为False时,将当前行索引添加到正常列,然后将当前行索引变为 0,1,2,⋯0,1,2,cdots0,1,2,⋯ 的形式
为True时,丢弃当前行索引,将当前行索引变为 0,1,2,⋯0,1,2,cdots0,1,2,⋯ 的形式
① 使用str预定义的函数
一些基本函数: / / / 、、 /
分割字符串:
② 字符串直接拼接:利用重载的 运算符
③ 面对复杂情况,可以使用上面介绍过的应用自定义函数
这里以一个这样的数据集为例(以下为数据前五行)
① 日期是一个Timestamp(时间戳)对象,日期的差为时间差(Timedelta)对象
常用格式字符:
- :4 位数的年份
- :2 位数的年份
- :2 位数的月份(01 到 12)
- :2 位数的日期(01 到 31)
- :24 小时制的小时数(00 到 23)
- :12 小时制的小时数(01 到 12)
- :2 位数的分钟数(00 到 59)
- :2 位数的秒数(00 到 59)
- :6 位数的微秒数
② 常用操作:转为日期类型 / 日期相减得到时间差 / 时间差计算时间间隔 / 星期几
两个时间戳(timestamp)相减得到一个时间差(timedelta)
③ 从日期数据进行数据过滤
- filt_1:上车时间在四月份
- filt_2:下车时间在四月份
- filt_3:在车上的时间在一分钟至三小时之间
① 分类统计信息:groupby + apply
- 待处理表格```
def mean_traveltime_mins(x): # 传进来的x是当前分组的数据
return x[‘duration_secs’].mean()
data.groupby([‘PULocationID’]).apply(mean_traveltime_mins).head()
def gb_count_filt(df, min_trips):
if len(df) < min_trips:
return False
return True
data_bg = data.groupby([‘PULocationID’, ‘isweekend’])
data_bg = data_bg.filter(gb_count_filt, min_trips=500)
print(data_bg.shape) # (207312, 8)
def mean_traveltime_df(df):
return pd.Series({‘mean_min’: df[‘duration_secs’].mean()/60, ‘median_min’: df[‘duration_secs’].median()/60, ‘count’: len(df)})
time_sum_min = data.groupby([‘PULocationID’, ‘isweekend’]).apply(mean_traveltime_df)
time_sum_min.reset_index().head(3)
time_sum = time_sum.sort_values(‘mean_min’, ascending=True) # 根据均值进行排序,ascending默认为True(升序)
time_sum.head(3)
time_sum[‘rank’] = time_sum[‘mean_min’].rank(ascending=False)
time_sum.head(3)
pd.concat([workout1, workout2], axis=0)
pd.concat([workout1, workout2], axis=1)
workout_dict1 = {
‘calories’: [420, 300, 800, 100],
‘duration’: [40, 20, 30, 10],
‘type’: [‘run’, ‘ride’, ‘jump’, ‘walk’],
}
workout_dict2 = {
‘test_1’: [12, 21],
‘duration’: [30, 40],
‘test_2’: [‘a’, ‘b’],
}
workout1 = pd.Dataframe(workout_dict1)
workout2 = pd.Dataframe(workout_dict2)
workout1 = workout1.set_index(‘duration’)
workout2 = workout2.set_index(‘duration’)
workout = workout1.join(workout2, how=‘left’, rsuffix=‘_2’)
workout = workout.reset_index() # 拼接后的索引为workout1的索引, workout2的索引自动删除
workout = workout1.merge(workout2, left_on=‘duration’, right_on=‘duration’, how=‘left’)
df_2 = df_1.pivot(index=‘Team’, columns=‘Variable’, values=‘Value’)
workout.loc[‘day1’][‘calories’] = 420
print(workout[‘calories’][‘day1’]) # 430