本文章参考网络视频以及菜鸟教程等内容进行Pandas核心内容的整理,包括大部分当时最常用的一些功能,帮助快速入门或复习Pandas。
文章内容
- 根底操作
- 目标创立和数据检查
- 实际作业常用命令
- 常用作业流
- 字符串、时刻信息的处理
- 表格的排序和拼接
- 长表格转宽表格
- 注意事项
介绍
Pandas是什么
Pandas,python+data+analysis的组合缩写,是python中根据numpy和matplotlib的第三方数据剖析库,与后两者一起构成了python数据剖析的根底东西包,广泛运用在学术、金融、核算学等各个数据剖析领域。
数据结构
① Series:类似表格中的一个列(column),类似于一维数组,能够保存任何数据类型。由索引(index)和列组成

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

根底操作-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序列三大特点:name
,values
,index
-
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
假如参数
index
和columns
未指定,默以为 RangeIndex(0, 1, 2,…, n),也便是 0,1,2,⋯0,1,2,\cdots
① 运用Python列表创立DataFrame目标

workout_dict = [
[420, 300, 800, 100],
[40, 20, 30, 10],
['run', 'ride', 'jump', 'walk'],
]
workout = pd.DataFrame(workout_dict)
运用这种方法创立的
DataFrame
表格,默许是按列的,每个子列表的榜首个元素构成表格中的每列(Series
)
② 运用Python字典创立DataFrame目标

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目标


# 指定多个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目标

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
列元素中的次序和榜首列中元素次序相同.
⑤ 在字典中不指定行索引,创立目标时指定行索引

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,标明空值.
⑥ 在字典中指定队伍索引后,创立目标时挑选指定队伍索引

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表格目标的索引

# 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目标的特点
index
和columns
赋值能够更改整个行索引或列索引.更改部分索引时,也能够单独指定
columns
参数或index
参数,若不指定则不更改.
拜访DataFrame表格中的列与行

# 创立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) |

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'>
该办法与上方的三种办法的不一起,得到的数据是该元素的数据类型,而上方的办法回来的都是DataFrame
或Series
类型.
根底操作-2:实际作业常用命令
外部数据的读取
① 读取excel文件(xlsx
、xls
)
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
:加载不同的数据封装格局,常用records
,index
,columns
data=pd.read_json('E:\Project\data.json', orient='records')
orient = 'records'
:多个字典组成的列表
orient = 'index'
:key作为行索引
orient = 'columns'
:key作为列索引
这儿介绍这四种文件的读取操作,根本满意大多状况
数据根本信息预览
创立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'])
① 数据根本信息预览:.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')
进程拆解:

# 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()
函数之后运用,也便是对数据分组后进行核算信息核算

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
索引设置

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


不保存(左),保存(右)
# 设置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


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
② 字符串直接拼接:运用重载的 +
运算符

# 拼接LastName和Sex,组成一个新的column添加到表格中
data['LastName'] = data['LastName'].astype('string') # 转为string类型
data['NameSex'] = data['LastName'] + '\_' + data['Sex']
data[['LastName', 'Sex', 'NameSex']][:3]
③ 面临复杂状况,能够运用上面介绍过的.apply()
运用自界说函数

# 给每行数据添加信息字段
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]
时刻信息的处理
这儿以一个这样的数据集为例(以下为数据前五行)

① 日期是一个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 位数的微秒数

② 常用操作:转为日期类型 / 日期相减得到时刻差 / 时刻差核算时刻距离 / 星期几
# 仅保存乘客上下车的时刻
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:在车上的时刻在一分钟至三小时之间

# 出行时刻可视化
data['hour'].plot.hist(bins=300) # bins=300标明将数据分成300个等宽的区间,并在每个区间上绘制一个条形
split-apply-combine
① 分类核算信息:groupby + apply

# 根据上车地址编号核算每个地址上车游客的平均出行时刻
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
中的是按PULocationID
和isweekend
划分的分组,在确认地址编号的前提下,又根据isweekend
分为了两组,然后根据每一个这样进一步划分的组来判别长度是否大于500
③ apply回来Series序列,一次拓宽多个列

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将这两个字段取消行索引变为一般列.
表格排序
根据列排序(默以为升序)

time_sum = time_sum.sort_values('mean_min', ascending=True) # 根据均值进行排序,ascending默以为True(升序)
time_sum.head(3)
运用函数sort_values按某一字段进行排序

# 运用rank生成数据排名
time_sum['rank'] = time_sum['mean_min'].rank(ascending=False)
time_sum.head(3)
运用函数rank按某一字段生成排名,这儿是按字段
mean_min
生成每条数据中按该字段得到的排名并作为一个新的column添加到表格中
若想运用本来的次序,直接调用函数.sort_index()
即可.
表格拼接
-
.concat()
:依照行或列的方向简略拼接 -
.join()
:依照行的索引index进行拼接 -
.merge()
:依照列的值作为根据进行拼接
运用concat()函数:直接进行拼接


- 待处理表格
workout1
和workout2

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

pd.concat([workout1, workout2], axis=1)
运用join()函数:以索引为根据进行拼接

# 运用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()函数:以指定列为根据进行拼接

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

运用.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:运用
loc
、iloc
在单个括号中定位或直接运用[]
的串联赋值是允许的,但是关于单个元素的重构/赋值一般会用之前介绍过的.at[]
来获取元素并进行赋值,在运用前能够运用df.copy()
对原数据进行保存.上面那种链式索引方法会回来一个仿制(copy),而不是原始的 DataFrame 目标,因而无法直接对其进行赋值操作,而
loc
或iloc
的多标签索引方法和直接运用[]
的链式索引方法回来的都是原数据的视图(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)