本文章参考网络视频以及菜鸟教程等内容进行Pandas核心内容的整理,包括大部分当时最常用的一些功能,帮助快速入门或复习Pandas。

文章内容

  • 根底操作
    • 目标创立和数据检查
    • 实际作业常用命令
  • 常用作业流
    • 字符串、时刻信息的处理
    • 表格的排序和拼接
    • 长表格转宽表格
  • 注意事项

介绍

Pandas是什么

Pandas,python+data+analysis的组合缩写,是python中根据numpy和matplotlib的第三方数据剖析库,与后两者一起构成了python数据剖析的根底东西包,广泛运用在学术、金融、核算学等各个数据剖析领域。

数据结构

① Series:类似表格中的一个列(column),类似于一维数组,能够保存任何数据类型。由索引(index)和列组成

【Python|Pandas】Pandas库核心内容

② DataFrame:表格型的数据结构,它含有一组有序的列,每列能够是不同的值类型(数值、字符串、布尔型值)。DataFrame 既有行索引也有列索引,它能够被看做由多个 Series 组成的字典(一起用一个索引)。

【Python|Pandas】Pandas库核心内容

根底操作-1:目标创立和数据检查

创立Series目标

pandas.Series( data, index, dtype, name, copy):创立一个Series目标

  • data:一组数据(ndarray)
  • index:数据索引标签,默以为0
  • dtype:数据类型,默许主动判别
  • name:设置称号
  • copy:仿制数据,默以为False

① 由列表创立Series

创立时不指定索引和称号

lst = [10, 20, 30]
lst_series = pd.Series(lst)
print(lst_series)
# 0    10
# 1    20
# 2    30
# dtype: int64

默许索引为RangeIndex,也便是 0,1,2,⋯0, 1, 2,\cdots

创立时指定索引(行索引)和称号(每行的称号,在表格中作为列索引或行索引)

lst = [10, 20, 30]
lst_series = pd.Series(lst, index=['index-1', 'index-2', 'index-3'], name='test_lst')
print(lst_series)
# index-1    10
# index-2    20
# index-3    30
# Name: test_lst, dtype: int64

② 由字典创立Series

dic = {'10': 11, '20': 21, '30': 31}
dic_series = pd.Series(dic, index=['10', '30', 'test_index'], name='test_lst')
print(dic_series)
# 10            11.0
# 30            31.0
# test_index     NaN
# Name: test_lst, dtype: float64

由列表创立需求指定行索引或称号,由字典创立若已在字典中指定过行索引了,在创立Series中再次指定为在其间的索引中进行挑选,若在办法中指定在字典中不存在的索引,将会为空值NaN (Not a Number).

③ Series序列三大特点:namevaluesindex

  • name:前面提到过,便是该序列的称号,组装成DataFrame后会成为表格的column或index(下面会介绍)
  • values:Series序列中的一切值
  • index:Series序列的索引值
ser = pd.Series([10, 20, 30], name='test_series', index=['day1', 'day2', 'day3'])
print(ser.name)  # test_series
print(ser.values)  # [10 20 30]
print(ser.index)  # Index(['day1', 'day2', 'day3'], dtype='object')

创立DataFrame目标

pandas.DataFrame(data, index, columns, dtype, copy):DataFrame结构办法

  • data:一组数据(ndarray, series, map, lists, dict 等类型)
  • index:索引值 / 行标签
  • columns:列标签
  • dtype:数据类型
  • copy:仿制数据,默以为False

假如参数 indexcolumns未指定,默以为 RangeIndex(0, 1, 2,…, n),也便是 0,1,2,⋯0,1,2,\cdots

① 运用Python列表创立DataFrame目标

【Python|Pandas】Pandas库核心内容

workout_dict = [
    [420, 300, 800, 100],
    [40, 20, 30, 10],
    ['run', 'ride', 'jump', 'walk'],
    ]
workout = pd.DataFrame(workout_dict)

运用这种方法创立的DataFrame表格,默许是按列的,每个子列表的榜首个元素构成表格中的每列(Series)

② 运用Python字典创立DataFrame目标

【Python|Pandas】Pandas库核心内容

import pandas as pd
# 运用python字典创立DataFrame表格
workout_dict = {
    'calories': [420, 300, 800, 100],
    'duration': [40, 20, 30, 10],
    'type': ['run', 'ride', 'jump', 'walk'],
    }
workout = pd.DataFrame(workout_dict)

pd.DataFrame() 传入一个字典,根据字典创立表格(DataFrame)目标;字典中的key为表格中的column称号,也便是列索引,每行默许是列表中对应元素的索引,也便是行索引.

③ 运用Series目标创立DataFrame目标

【Python|Pandas】Pandas库核心内容
【Python|Pandas】Pandas库核心内容

# 指定多个Series创立,默许Series称号作为行索引,元素横向摆放(左图)
test_series = pd.Series([1,2,3], name='test')
test_df1 = pd.DataFrame([test_series, test_series])
print(test_df1)
# 指定单个Series创立,默许Series称号作为列索引,元素纵向摆放(右图)
test_df2 = pd.DataFrame(test_series)
print(test_df2)

④ 在字典中指定每行的行索引创立DataFrame目标

【Python|Pandas】Pandas库核心内容

workout_dict = {
    'calories': {'day1': 420, 'day2': 300, 'day3': 800, 'day4': 100},
    'duration': {'day2': 40, 'day1': 20, 'day3': 30, 'day4': 10},
    'type': {'day3': 'run', 'day2': 'ride', 'day1': 'jump', 'day4': 'walk'},
    }
workout = pd.DataFrame(workout_dict)

也能够指定行索引,在指定行索引时,默许按字典中榜首个元素的行索引次序,例如上方事例中’duration’列和type列元素中的次序和榜首列中元素次序相同.

⑤ 在字典中不指定行索引,创立目标时指定行索引

【Python|Pandas】Pandas库核心内容

workout_dict = {
    'calories': [420, 300, 800, 100],
    'duration': [40, 20, 30, 10],
    'type': ['run', 'ride', 'jump', 'walk'],
    }
workout = pd.DataFrame(workout_dict, index=['day1', 'day2', 'day3', 'day4'])

指定行索引中按次序与本来索引对应,超出数量的索引也会创立,但元素用空值’NaN’替代

NaN:Not a Number,标明空值.

⑥ 在字典中指定队伍索引后,创立目标时挑选指定队伍索引

【Python|Pandas】Pandas库核心内容

workout_dict = {
    'calories': {'day1': 420, 'day2': 300, 'day3': 800, 'day4': 100},
    'duration': {'day2': 40, 'day1': 20, 'day3': 30, 'day4': 10},
    'type': {'day3': 'run', 'day2': 'ride', 'day1': 'jump', 'day4': 'walk'},
    }
workout = pd.DataFrame(workout_dict, columns=['calories', 'type', 'test_column'], index=['day1', 'day2', 'day4', 'test_row'])

若选中未指定的索引,则该列或该行的值为空值

⑦ 将DataFrame表格转换回Python字典

print(workout.to_dict())
# {
# 'calories': {0: 420, 1: 300, 2: 800, 3: 100},
# 'duration': {0: 40, 1: 20, 2: 30, 3: 10},
# 'type': {0: 'run', 1: 'ride', 2: 'jump', 3: 'walk'},
# }

DataFrame目标运用to_dict()办法即可转换回python字典,但是对应字典是上述方法,即字典中的value也是字典,该字典的key为DataFrame中的行索引,value为值.

拜访或更改DataFrane表格中索引

① 拜访整个列索引(column index)或行索引(row index)

# workout是上面创立的DataFrame目标
print(workout.columns)   # 列索引 Index(['calories', 'duration', 'type'], dtype='object')
print(workout.index)   # 行索引 RangeIndex(start=0, stop=4, step=1)
# 有时会转换成列表处理
print(workout.columns.tolist())   # ['calories', 'duration', 'type']
print(workout.index.tolist())   # [0, 1, 2, 3]

拜访DataFrame的索引相关特点,tolist()办法可转换成python中的list目标.

② 更改DataFrame表格目标的索引

【Python|Pandas】Pandas库核心内容

# workout是上面创立的DataFrame目标
workout.index = ['day-1', 'day-2', 'day-3', 'day-4']    # 更改整个行索引
workout.columns = ['colories', 'duration', 'type']   # 更改整个列索引
# 更改部分行索引或列索引
workout = workout.rename(columns={'colories': 'col', 'duration': 'dura'}, index={'day-4': 'day4'}) 

直接对DataFrame目标的特点indexcolumns赋值能够更改整个行索引或列索引.

更改部分索引时,也能够单独指定columns参数或index参数,若不指定则不更改.

拜访DataFrame表格中的列与行

【Python|Pandas】Pandas库核心内容

# 创立DataFrame表格
workout_dict = {
    'calories': [420, 300, 800, 100],
    'duration': [40, 20, 30, 10],
    'type': ['run', 'ride', 'jump', 'walk'],
    }
workout = pd.DataFrame(workout_dict, index=['day1', 'day2', 'day3', 'day4'])

① 挑选表格中的列与行 ([])

print(workout['calories'])   # 挑选一列, 回来Series序列目标
# day1    420
# day2    300
# day3    800
# day4    100
# Name: calories, dtype: int64
print(type(workout['calories']))   # <class 'pandas.core.series.Series'>
print(workout[['calories', 'type']])   # 双口号能够挑选多个列, 回来DataFrame表格目标
#       calories  type
# day1       420   run
# day2       300  ride
# day3       800  jump
# day4       100  walk
# <class 'pandas.core.frame.DataFrame'>
# 挑选列后若为Series目标则可进一步挑选行(索引或行称号)
print(workout['calories']['day1'])  # 420
# DataFrame目标能够用索引指定行(索引或称号)
print(workout['calories'][0])  # 420
# 直接用索引切片默许标明一切列的行
print(workout[0:2])
#       calories  duration  type
# day1     420     40    run
# day2     300     20    ride
# 当然也能够选中某一列运用切片操作
print(workout['calories'][0:2])
# day1    420
# day2    300
# Name: calories, dtype: int64
  • 若运用一个[]且是切片操作,仅支持行索引称号切片或行索引数字切片.
  • 若运用一个[]且内嵌一个[],则标明挑选列索引,但不支持列索引切片和数字切片操作.
  • 若运用一个[]且非切片操作,则榜首个[]标明挑选列索引.
  • 注:列索引不能切片或用数字标明,行索引能够切片或用数字标明,且切片操作若为标签切片的话包括最终一个数据,若为整数切片则不含最终一个数据。

② 挑选表格中的列与行 (.loc[], .iloc[])

# .loc[]
print(workout.loc['day1',:])
# calories    420
# duration    40
# type      run
# Name: day1, dtype: object
print(workout.loc[['day1', 'day2'], 'calories'], workout.loc[['day1', 'day2'], 'calories'])
# day1    420
# day2    300
# Name: calories, dtype: int64
print(workout.loc['day1':'day3', 'calories'], type(workout.loc['day1':'day2', 'calories']))
# day1    420
# day2    300
# day3    800
# Name: calories, dtype: int64 <class 'pandas.core.series.Series'>
print(workout.loc['day1':'day2', 'calories':'duration'], type(workout.loc['day1':'day2', 'calories':'duration']))
#       calories  duration
# day1       420        40
# day2       300        20 <class 'pandas.core.frame.DataFrame'>
# .iloc[]
print(workout.iloc[0, :], type(workout.iloc[0, :]))
# calories    420
# duration    40
# type      run
# Name: day1, dtype: object <class 'pandas.core.series.Series'>
print(workout.iloc[[0 ,1, 2], [0, 1]], type(workout.iloc[[0 ,1, 2], [0, 1]]))
#       calories  duration
# day1       420        40
# day2       300        20
# day3       800        30 <class 'pandas.core.frame.DataFrame'>

.iloc[].loc[][]之间的差异:

三种办法都能用布尔值来标明索引,如下所示

print(workout[[True, True, True, False]])
#       calories  duration  type
# day1     420     40   run
# day2     300     20   ride
# day3     800     30   jump
print(workout.iloc[[True, True, True, False], [True, True, False]])
#       calories  duration
# day1     420     40
# day2     300     20
# day3     800     30
print(workout.loc[[True, True, True, False], [True, True, False]])
#       calories  duration
# day1     420     40
# day2     300     20
# day3     800     30

.iloc[].loc[]之间的差异:

  • .loc[]函数:根据行标签和列标签进行索引的,切片时包括最终一个数据,不能对columns直接运用整数索引.
  • .iloc[]函数:根据行和列的方位进行索引的,索引值从0开始,并且切片时不包括最终一个数据, i标明integer,关于index和columns,.iloc[]只能用整数来索引.

[]之间的一些差异:

  • []在一个中括号中只能填一次,不能用逗号距离一次一起做挑选行和列操作
  • []中若非切片操作,则其间为列索引,而另外两种办法[]中的榜首组值都为行索引.

Pandas中也有一些其它的数据挑选操作,但不常用也不引荐运用,这三种办法现已根本能够满意需求了.

④ 过滤数据

过滤数据:

符号 意义 运算规矩
~ 按位取反(not) (T,F) → (F,T)
& 按位取和(and) (T,T,F,F) & (T,F,T,F) → (T,F,F,F)
| 按位取或(or) (T,T,F,F) | (T,F,T,F) → (T,T,T,F)

【Python|Pandas】Pandas库核心内容

filt = ~workout['calories'].isnull()  # workout表格中calories字段下的非空值地址的行
workout.loc[filt]  # 赋值后效果等同于删去了calories字段下存在缺失值的数据

⑤ 假如拜访单个值的话也能够用.at[]

print(workout.at['day1','calories'], type(workout.at['day1','calories']))  # 420 <class 'numpy.int64'>

该办法与上方的三种办法的不一起,得到的数据是该元素的数据类型,而上方的办法回来的都是DataFrameSeries类型.

根底操作-2:实际作业常用命令

外部数据的读取

① 读取excel文件(xlsxxls)

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:列名命名或重命名,默许不变
data = pd.read_excel('E:\Project\data.xls', sheetname = 'sheet1',header =0)

② 读取csv文件

pd.read_csv(path):读取csv文件

  • path:要读取的文件途径
  • sep:指定列与列间的分隔符,默许sep = ‘,’
    • 若sep = ‘\t’,即列与列间用制表符\t分隔;
    • 若sep = ‘,’,即列与列间用逗号分隔;
  • header:用作列名的行号,默以为0
    • 若header = None,则标明数据中没有列名行;
    • 若header = 0,则标明榜首行为列名;
  • names:列名命名或重命名,默许不变
  • encoding:指定用于unicode文本编码格局
    • 若encoding = ‘utf-8’,则标明用UTF-8编码的文本;
    • 若encoding = ‘gbk’,则标明用gbk编码的文本;
data = pd.read_csv('E:\Project\data.csv', sep = ',',header=0,names=['主题分类','发文组织','施行日期'], encoding='utf-8')

③ 读取txt文件

pandas中的pd.read_csv()即能够读取csv文件,也能够读取txt文件办法同上,也能够用pd.read_table()读取txt文件,差异在于sep的默许参数不同.

pd.read_table()

  • path:要读取的文件绝对途径
  • sep:指定列与列间的分隔符,默许sep = ‘\t’
    • 若sep = ‘\t’,即列与列间用制表符\t分隔;
    • 若sep = ‘,’,即列与列间用逗号,分隔;
  • header:用作列名的行号,默以为header = 0
    • 若header = None,则标明数据中没有列名行;
    • 若header = 0,则标明榜首行为列名;
  • names:列名命名或重命名,默许不变
data = pd.read_table('E:\Project\data.txt', sep = '\t', header = 1)

④ 读取JSON文件

pd.read_json(path)

  • path:文件途径
  • orient:加载不同的数据封装格局,常用 recordsindex,columns
data=pd.read_json('E:\Project\data.json', orient='records')

orient = 'records':多个字典组成的列表

  • json文件结构事例:

    • '[{"name":"ysh","age":"18"},{"name":"cjy"},{"age":"17"}]'
  • 读取后:

    【Python|Pandas】Pandas库核心内容

orient = 'index':key作为行索引

  • json文件结构事例:

    • '{"city":{"guangzhou":"20","zhuhai":"20"},"home":{"price":"5W","data":"10"}}'
  • 读取后:

    【Python|Pandas】Pandas库核心内容

orient = 'columns':key作为列索引

  • json文件结构事例:

    • '{"city":{"guangzhou":"20","zhuhai":"20"},"home":{"price":"5W","data":"10"}}'
  • 读取后:

    【Python|Pandas】Pandas库核心内容
    .

这儿介绍这四种文件的读取操作,根本满意大多状况

数据根本信息预览

创立DataFrame表格

【Python|Pandas】Pandas库核心内容

workout_dict = {
    'calories': [420, 300, 800, 100],
    'duration': [40, 20, 30, 10],
    'type': ['run', 'ride', 'jump', 'walk'],
    }
workout = pd.DataFrame(workout_dict, index=['day1', 'day2', 'day3', 'day4'])

① 数据根本信息预览:.head(n) / .tail(n) / .sample(n)

  • .head(n):打印前n行数据,默许n为5
  • .tail(n):打印后n行数据,默许n为5
  • .sample(n):打印随机n行数据,默许n为5
workout.head(2)
# 	 calories 	duration 	type
# day1	420	     40	   run
# day2	300	     20	   ride
workout.tail(2)
#	   calories	 duration	 type
# day3	800	   30	   jump
# day4	100	   10	   walk
workout.sample(2)
# 	 calories	 duration	 type
# day3	800	    30	  jump
# day1	420	    40	  run  

② 表格根本信息预览:.shape() / .len() / .dtypes() / .describe() /.info()

  • .shape:打印表格形状,(行数,列数)
  • .len():打印表格长度(行数)
  • .dtypes:打印表格中的行索引和该Series的元素数据类型,回来一个Series
  • .describe():打印数值类型数据根本核算信息,包括:
    • count:元素数量
    • mean:平均数
    • std:标准差
    • min:最小值
    • 25% / 50% / 70%:四分位数
    • max:最大值
  • .info():表格根本信息,包括:
    • 数据结构、行/列索引数,每个Series的数据类型,所占内存等
print(workout.shape)  # (4, 3)
print(len(workout))  # 4
print(workout.dtypes, type(workout.dtypes))
# calories     int64
# duration     int64
# type        object
# dtype: object <class 'pandas.core.series.Series'>
print(workout.describe())
#       calories   duration
# count    4.000000   4.000000
# mean   405.000000  25.000000
# std    294.561821  12.909944
# min    100.000000  10.000000
# 25%    250.000000  17.500000
# 50%    360.000000  25.000000
# 75%    515.000000  32.500000
# max    800.000000  40.000000
print(workout.info())
# <class 'pandas.core.frame.DataFrame'>
# Index: 4 entries, day1 to day4
# Data columns (total 3 columns):
#  #   Column    Non-Null Count  Dtype 
# ---  ------    --------------  ----- 
#  0   calories  4 non-null      int64 
#  1   duration  4 non-null      int64 
#  2   type      4 non-null      object
# dtypes: int64(2), object(1)
# memory usage: 128.0+ bytes

③ 核算性信息操作:.unique() / .nunique() / .groupby() / .agg() /.apply()

  • .unique():回来一个由Series中仅有的元素组成的列表 (ps:DataFrame目标没这个办法)
  • .nunique():回来仅有值元素的个数(Series和DataFrame目标都能用,后者回来的是其间一切Series和其对应的仅有值数量,能够进一步运用.sum()求和)
  • .groupby():根据某个(多个)字段划分为不同的组(group)
  • .apply():用于将某个函数运用于表格中的每个Series或Series中的每个值
  • .agg():对数据核算核算信息,一般在.groupby()之后运用

.unique() / .nunique():仅有值 / 仅有值个数

# unique() / nunique()
print(workout['calories'].unique())  # [420 300 800 100]
print(workout['calories'].nunique())  # 4
print(workout.nunique(), type(workout.nunique()))
# calories    4
# duration    4
# type      4
# dtype: int64
# dtype: int64 <class 'pandas.core.series.Series'>
print(workout.nunique().sum(), type(workout.nunique().sum()))  # 12 <class 'numpy.int64'>

.groupby():分组,回来一个DataFrameGroupBy目标,直接打印为其内存地址 (能够转为list进行检查)

一般会在履行分组后进行其它操作,下面会解说

例:groupby(by='company')进程拆解:

【Python|Pandas】Pandas库核心内容

# groupby()
workout_by_calories = workout.groupby('calories')
print(workout_by_calories)  # <pandas.core.groupby.generic.DataFrameGroupBy object at 0x785533b98100>
print(list(workout_by_calories))
# [
# (100,  calories  duration  type 
# day4    100    10    walk),
# (300,  calories  duration  type 
# day2    300    20    ride),
# (420,  calories  duration type  
# day1    420    40    run),
# (800,  calories  duration  type 
# day3    800    30    jump),
# ]

能够看出,因为workout中的calories中四个元素都不同,按calories分组也就意味着按每个元素单独分为一组,用转为list之后数据来阐明,每个分组为一个元组,每个元组中榜首个元素为分类根据的元素,后边几个元素为数据的columns标签,然后开始为每一条分组数据的行索引和数据。

核算核算信息:.agg()

.agg()函数经常在.groupby()函数之后运用,也便是对数据分组后进行核算信息核算

【Python|Pandas】Pandas库核心内容

def percentile_25(x):
  return x.quantile(0.25)
def percentile_75(x):
  return x.quantile(0.75)
# 按类别(pclass)和是否幸存(survived)分组后,核算这些分组中年龄的信息
age_agg = data[['Pclass', 'Survived', 'Age']].groupby(['Pclass', 'Survived']).agg(['min', 'max', 'median', 'mean', len, np.std, percentile_25, percentile_75])
age_agg

这儿的数据集以泰坦尼克号中的练习集为例

percentile:百分数,quantile:量值;便是回来数据中的四分位数

.agg()函数处理后的数据为DataFrame目标,事例中的行和列都是多级的索引

print(type(age_agg))  # <class 'pandas.core.frame.DataFrame'>
print(age_agg.columns)
# MultiIndex([('Age', 'min'),
#       ('Age', 'max'),
#       ('Age', 'median'),
#       ('Age', 'mean'),
#       ('Age', 'len'),
#       ('Age', 'std'),
#       ('Age', 'percentile_25'),
#       ('Age', 'percentile_75')],
#       )
print(age_agg.index)
# MultiIndex([(1, 0),
#       (1, 1),
#       (2, 0),
#       (2, 1),
#       (3, 0),
#       (3, 1)],
#       names=['Pclass', 'Survived'])

.apply(func, axis=0, raw=False)

  • func:传入的函数或Lambda表达式
  • axis:默以为0(列),0或index(列)1或columns(行)
  • raw:默以为False,False ,标明把每一行或列作为 Series 传入函数中;True,标明接受的是 ndarray 数据类型
# 原始数据
print(workout)
#      calories  duration  type
# day1    420     40    run
# day2    300     20    ride
# day3    800     30    jump
# day4    100     10    walk
# 核算数值类型的每个元素的平方根
print(workout.iloc[:, :2].apply(np.sqrt))  # 对挑选的每个Series运用np.sqrt()函数
#     calories  duration
# day1  20.493902  6.324555
# day2  17.320508  4.472136
# day3  28.284271  5.477226
# day4  10.000000  3.162278
# 核算每一行数值类型的平均值
print(workout[['calories', 'duration']].apply(np.mean, axis=1))
# day1    230.0
# day2    160.0
# day3    415.0
# day4    55.0
# dtype: float64
# 将这两个column相加并作为一个新的column字段添加到表格中
workout['cal+dura'] = workout.iloc[:, :2].apply(lambda w: w.calories+w['duration'], axis=1)  # 这儿只是用了不同的写法
print(workout)
#       calories  duration  type  cal+dura
# day1     420     40    run   460
# day2     300     20    ride   320
# day3     800     30    jump   830
# day4     100     10    walk   110

处理的若为Series,则为每个元素运用函数func

索引设置

【Python|Pandas】Pandas库核心内容

① .set_index():将某一列设置为index

  • keys:需求设置为index的列名
  • drop:布尔值,在将本来的列设置为index,是否需求删去本来的列,默以为True
  • append:布尔值,新的index设置之后,是否要删去本来的index,默以为True
  • inplace:布尔值,是否进行原地操作,即是否要用新的DataFrame取代本来的DataFrame,默许False

【Python|Pandas】Pandas库核心内容
【Python|Pandas】Pandas库核心内容

不保存(左),保存(右)

# 设置calories为新的行索引index,不保存本来的行索引和本来的Series
workout.set_index('calories')
# 设置calories为新的行索引行索引index,保存本来的行索引和Series
workout.set_index('calories', drop=False, append=False)
# 多个行索引的状况
workout_test = workout.set_index('type', drop=False, append=True)
workout_test.loc['day1']
# 	 calories	duration type
# type			
# run	  420	  40	 run
workout_test.loc['day1'].loc['run']
# calories    420
# duration    40
# type      run
# Name: run, dtype: object

当表格中含有多个行索引时,关于该表格,只能运用最外层行索引确认,确认后能够进一步运用内层行索引确认

② reset_index():从头设置表格的行索引

  • drop:布尔值,标明是否舍弃当时行索引,默以为False

【Python|Pandas】Pandas库核心内容
【Python|Pandas】Pandas库核心内容

workout.reset_index(drop=False)   # 图左
workout.reset_index(drop=True)    # 图右

drop为False时,将当时行索引添加到正常列,然后将当时行索引变为 0,1,2,⋯0,1,2,\cdots 的方法

drop为True时,丢掉当时行索引,将当时行索引变为 0,1,2,⋯0,1,2,\cdots 的方法

常用作业流

字符串处理

① 运用str预界说的函数

一些根本函数:.lower() / .upper() / .len() / .strip().lstrip().rstrip() / .replace()

data['Name'].str.lower()[:3]  # 字符串字母小写
data['Name'].str.upper()[:3]  # 字符串字母大写
data['Name'].str.len()[:3]   # 字符串长度
# strip(), lstrip(), rstrip():去除前后空格
data['Name'].str.strip()[:3]
data['Name'].str.replace(' ','_')  # replace(被替换字符,替换字符)
# 链式编程
data['Name'].str.strip().str.lower().str.replace(' ','_')

分割字符串:.split()

data['LastName'] = data['Name'].str.split(',').str[0]  # 取出榜首个名字(名字由逗号分隔)
data['LastName'][:3]
# 0    Braund
# 1    Cumings
# 2    Heikkinen
# Name: LastName, dtype: object

② 字符串直接拼接:运用重载的 + 运算符

【Python|Pandas】Pandas库核心内容

# 拼接LastName和Sex,组成一个新的column添加到表格中
data['LastName'] = data['LastName'].astype('string')  # 转为string类型
data['NameSex'] = data['LastName'] + '\_' + data['Sex']
data[['LastName', 'Sex', 'NameSex']][:3]

③ 面临复杂状况,能够运用上面介绍过的.apply()运用自界说函数

【Python|Pandas】Pandas库核心内容

# 给每行数据添加信息字段
def add_message(x):
  prefix, survive_str = 'Mr.', 'died'
  if x['Sex'] == 'femail':
    prefix='Ms.'
  if x['Survived'] == 1:
    survive_str = 'survived'
  msg = f'{prefix}{x.LastName}, {survive_str} at Titanic at the age of {x.Age}'
  return msg
data['Message'] = data.apply(add_message, axis=1)
data[['LastName', 'Sex', 'Age', 'Survived', 'Message']][:3]

时刻信息的处理

这儿以一个这样的数据集为例(以下为数据前五行)

【Python|Pandas】Pandas库核心内容

① 日期是一个Timestamp(时刻戳)目标,日期的差为时刻差(Timedelta)目标

# format参数是指定传入字符串的日期格局,默以为主动检测
time_start = pd.to_datetime('2022-01-01', format='%Y-%m-%d') 
print(type(time_start))  # <class 'pandas._libs.tslibs.timestamps.Timestamp'>
print(pd.to_timedelta('3day'))  # 3 days 00:00:00
print(pd.to_timedelta('3hour'))  # 0 days 03:00:00
print(pd.to_timedelta('3min'))  # 0 days 00:03:00
print(pd.to_timedelta('3s'))  # 0 days 00:00:03
print(type(pd.to_timedelta('3s')))  # <class 'pandas._libs.tslibs.timedeltas.Timedelta'>

常用格局字符:

  • %Y:4 位数的年份
  • %y:2 位数的年份
  • %m:2 位数的月份(01 到 12)
  • %d:2 位数的日期(01 到 31)
  • %H:24 小时制的小时数(00 到 23)
  • %I:12 小时制的小时数(01 到 12)
  • %M:2 位数的分钟数(00 到 59)
  • %S:2 位数的秒数(00 到 59)
  • %f:6 位数的微秒数

【Python|Pandas】Pandas库核心内容

② 常用操作:转为日期类型 / 日期相减得到时刻差 / 时刻差核算时刻距离 / 星期几

# 仅保存乘客上下车的时刻
data = data[['pickup_dt', 'dropoff_dt']]
# 字符串类型转为日期类型
data['pickup_dt'] = pd.to_datetime(data['pickup_dt'])
data['dropoff_dt'] = pd.to_datetime(data['dropoff_dt'])
# 核算乘客在车上的时刻
data['duration_time'] = data['pickup_dt'] - data['dropoff_dt']
# 将乘客在车上的时刻转化为秒
data['duration_secs'] = data['duration_time'].dt.seconds
# 将乘客在车上的时刻转化为小时
data['hour'] = data['duration_secs'] / 60 / 60
# 乘客搭车日期是星期几
data['week'] = data['pickup_dt'].dt.weekday
# 乘客搭车日期是否为休息日(周末),将日期转化为星期,然后判别是否大于5
# 0: Monday; 6: Sunday
data['isweekend'] = data['pickup_dt'].dt.weekday > 5
data.head()

两个时刻戳(timestamp)相减得到一个时刻差(timedelta)

③ 从日期数据进行数据过滤

time_start = pd.to_datetime('2020-04-01')
time_end = pd.to_datetime('2020-04-30 23:59:59')
filt_1 = (data['pickup_dt'] >= time_start) & (data['pickup_dt'] <= time_end)
filt_2 = (data['dropoff_dt'] >= time_start) & (data['dropoff_dt'] <= time_end)
filt_3 = (data['duration_time'] >= pd.to_timedelta('1min')) & (data['duration_time'] <= pd.to_timedelta('3hour'))
data_filt = data.loc[filt_1 & filt_2 & filt_3, :]
print(data_filt.shape)   # (233319, 7)
  • filt_1:上车时刻在四月份
  • filt_2:下车时刻在四月份
  • filt_3:在车上的时刻在一分钟至三小时之间

【Python|Pandas】Pandas库核心内容

# 出行时刻可视化
data['hour'].plot.hist(bins=300)  # bins=300标明将数据分成300个等宽的区间,并在每个区间上绘制一个条形

split-apply-combine

① 分类核算信息:groupby + apply

【Python|Pandas】Pandas库核心内容

– 待处理表格
# 根据上车地址编号核算每个地址上车游客的平均出行时刻
def mean_traveltime_mins(x): # 传进来的x是当时分组的数据
  return x['duration_secs'].mean()
data.groupby(['PULocationID']).apply(mean_traveltime_mins).head()
# PULocationID
# 1    376.125000
# 3    1113.454545
# 4    782.835664
# 5    3274.000000
# 6    1216.333333
# dtype: float64

② 分类核算信息:groupby + filter

# 筛选出出行次数大于500的上车地址编号分组
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)

这段代码中传到参数df中的是按PULocationIDisweekend划分的分组,在确认地址编号的前提下,又根据isweekend分为了两组,然后根据每一个这样进一步划分的组来判别长度是否大于500

③ apply回来Series序列,一次拓宽多个列

【Python|Pandas】Pandas库核心内容

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)

这儿用了apply函数之后,因为前面用了groupby分组,所以分组的两个column字段的值会作为行索引,这儿运用reset_index将这两个字段取消行索引变为一般列.

表格排序

根据列排序(默以为升序)

【Python|Pandas】Pandas库核心内容

time_sum = time_sum.sort_values('mean_min', ascending=True)   # 根据均值进行排序,ascending默以为True(升序)
time_sum.head(3)

运用函数sort_values按某一字段进行排序

【Python|Pandas】Pandas库核心内容

# 运用rank生成数据排名
time_sum['rank'] = time_sum['mean_min'].rank(ascending=False) 
time_sum.head(3)

运用函数rank按某一字段生成排名,这儿是按字段mean_min生成每条数据中按该字段得到的排名并作为一个新的column添加到表格中

若想运用本来的次序,直接调用函数.sort_index()即可.

表格拼接

  1. .concat():依照行或列的方向简略拼接
  2. .join():依照行的索引index进行拼接
  3. .merge():依照列的值作为根据进行拼接

运用concat()函数:直接进行拼接

【Python|Pandas】Pandas库核心内容
【Python|Pandas】Pandas库核心内容

  • 待处理表格 workout1workout2

【Python|Pandas】Pandas库核心内容

pd.concat([workout1, workout2], axis=0)

【Python|Pandas】Pandas库核心内容

pd.concat([workout1, workout2], axis=1)

运用join()函数:以索引为根据进行拼接

【Python|Pandas】Pandas库核心内容

# 运用python字典创立DataFrame表格
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的索引主动删去

join函数是按两个表格中的索引作为根据,根据两个索引相同的拼接在一起,参数how为拼接方法,left标明表格self作为左侧,参数rsuffix标明若遇到相同的列名则在后边添加的后缀以保证列名不重复.

运用merge()函数:以指定列为根据进行拼接

【Python|Pandas】Pandas库核心内容

# 表格和join函数示例中set_index后的表格相同
workout = workout1.merge(workout2, left_on='duration', right_on='duration', how='left')
# 这儿展示的结果没有进行reset_index

长表格和宽表格之间的转化

【Python|Pandas】Pandas库核心内容

运用.pivot()函数:

df_2 = df_1.pivot(index='Team', columns='Variable', values='Value')

df_1为图中的长表格

注意事项

① copy和view

要搞明白一些操作是对原表格数据的仿制仍是视图,假如是仿制的话,那么在新的仿制数据里进行的操作不会影响原数据,若为视图,则在新的数据进行修改,原数据也会收到影响 (两个目标指向同一内存地址)

Pandas中不能串联赋值单个元素:

workout.loc['day1']['calories'] = 420
print(workout['calories']['day1'])  # 430

ps:运用lociloc在单个括号中定位或直接运用[]的串联赋值是允许的,但是关于单个元素的重构/赋值一般会用之前介绍过的.at[]来获取元素并进行赋值,在运用前能够运用df.copy()对原数据进行保存.

上面那种链式索引方法会回来一个仿制(copy),而不是原始的 DataFrame 目标,因而无法直接对其进行赋值操作,而lociloc的多标签索引方法和直接运用[]的链式索引方法回来的都是原数据的视图(view),因而能够直接仿制

② Pandas的缺乏

一切数据躲在电脑内存中,能够存储的数据巨细有限,更大的数据需求建立数据库运用磁盘空间,也能够将大文件分割为小文件方便Pandas读取,真实的大数据分布式运算需求借助于Spark/PySpark这类分布式运算东西。

学习资源

  • Pandas中文文档:Pandas中文文档
  • Pandas英文文档:Pandas官方文档
  • 练习网站:Pandas入门练习题

Reference

  • 全文参考视频:良心总结帖:十分钟了解Pandas核心内容_哔哩哔哩_bilibili
  • 其它参考:
    • Pandas教程 | 超好用的Groupby用法详解 – 知乎 (zhihu.com)
    • Pandas 数据结构 – DataFrame | 菜鸟教程 (runoob.com)
    • 如何在pandas中运用set_index( )与reset_index( )设置索引 – 知乎 (zhihu.com)
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。