Pandas是一个强大的分析结构化数据的工具集;它的使用基础是Numpy(提供高性能的矩阵运算);用于数据挖掘和数据分析,同时也提供数据清洗功能。
Pandas 是 Python 的核心数据分析支持库,提供了快速、灵活、明确的数据结构,旨在简单、直观地处理关系型、标记型数据。
∙ \bullet ∙ 处理浮点与非浮点数据里的缺失数据,表示为 NaN;
∙ \bullet ∙ 大小可变:插入或删除 DataFrame 等多维对象的列;
∙ \bullet ∙ 自动、显式数据对齐:显式地将对象与一组标签对齐,也可以忽略标签,在 Series、 DataFrame 计算时自动与数据对齐;
∙ \bullet ∙ 强大、灵活的分组(group by)功能:拆分-应用-组合数据集,聚合、转换数据;
把 Python 和 NumPy 数据结构里不规则、不同索引的数据轻松地转换为 DataFrame 对象;
∙ \bullet ∙基于智能标签,对大型数据集进行切片、花式索引、子集分解等操作;
∙ \bullet ∙ 直观地合并(merge)、**连接(join)**数据集;
∙ \bullet ∙ 灵活地重塑(reshape)、**透视(pivot)**数据集;
∙ \bullet ∙ 轴支持结构化标签:一个刻度支持多个标签;
∙ \bullet ∙ 成熟的 IO 工具:读取文本文件(CSV 等支持分隔符的文件)、Excel 文件、数据库等来源的数据,利用超快的 HDF5 格式保存 / 加载数据;
∙ \bullet ∙ 时间序列:支持日期范围生成、频率转换、移动窗口统计、移动窗口线性回归、日期位移等时间序列功能
∙ \bullet ∙ 它是专门为了处理表格和混杂数据设计的
它是一种类似于一维数组的对象,是由一组数据(各种NumPy数据类型)以及一组与之相关的数据标签(即索引)组成。仅由一组数据也可产生简单的Series对象。
# 属性一:index
s.index # Index(['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'], dtype='object')
s.index=='B'
# array([False, True, False, False, False, False, False, False, False,False])
# 属性二:values
s.values # array([23, 29, 24, 22, 25, 6, 28, 20, 28, 14])
s.values==23 # array([ True, False, False, False, False, False, False, False, False,False])
s.values<25 # array([ True, False, True, True, False, True, False, True, False,True])
# 属性三:size
s.size # 10,返回元素的个数
# 属性四:shape
s.shape # (10,),获取形状
# 属性五:name
s.name = 'age'
s.index.name = 'gender'
格式:
pd.Series(data=None,index=None,dtype=None,name=None,copy=False,fastpath=False)
参数描述:index默认从0开始也可以自定义,可以为非整型。
name为表的名字
copy为复制输入的数据
创建series对象的两种方式:
∙ \bullet ∙ 列表元组等生成series对象
∙ \bullet ∙ 字典生成Series对象
直接传入一个字典
data = {'name':'tyl','age':25}
info = pd.Series(data)
info # name tyl
age 25
传入排好序字典的键以改变顺序
index1 = ['age','name','gender']
info1 = pd.Series(data,index=index1)
info1 # age 25
name tyl
gender nan
∙ \bullet ∙ array数组生成series对象
两者区别:
列表方式是生成一个副本,而array数组是引用。
在数据中使用np.nan表示空值
∙ \bullet ∙ 显式索引
s=pd.Series(data=np.random.randint(1,30,size=10),index=list('ABCDEFGHIJ')) # A 23
B 29
C 24
D 22
E 25
F 6
G 28
H 20
I 28
J 14
dtype: int32
通过索引的方式选取Series对象中的一组值或者单个值
s['C'] # 24
s[['A','G']] # A 23
G 28
s.loc['C'] # 24
# 使用loc取多个值,可以放重复的索引
s.loc[['A','D','J']] # A 23
D 22
J 14
dtype: int32
# 可以使用bool列表取值,但是bool列表长度需要和s对象元素个数一致
s.loc[[True,False,False,True,False,False,True,False,False,True]] # A 23
D 22
G 28
J 14
dtype: int32
使⽤NumPy函数或类似NumPy的运算(如根据布尔型数组进⾏过滤、标量乘法、应⽤数学函数等)都会保留索引值的链接
s[s>25] -> s[['B','G','I']] # B 29
G 28
I 28
∙ \bullet ∙ 隐式索引
默认从0开始
s[0] # 23
s[8] # 28
s.iloc[8] # 28
s.iloc[[8,0,5]] # I 28
A 23
F 6
dtype: int32
s.loc和s.iloc返回值都是Series类型
∙ \bullet ∙ 修改索引
就地赋值修改索引:s.index = [‘a’,‘b’,‘c’…]
∙ \bullet ∙ 显式索引与列表等的切片基本一致,但是顾左也顾右。
∙ \bullet ∙ 隐式索引顾左不顾右
s1 = pd.Series(data=np.random.randint(1,10,size=6),index=list('ABCDEF')) # A 4
B 2
C 3
D 8
E 3
F 2
dtype: int32
# 方法一:head(n) 获取前n个元素
s.head(2) # A 23
B 29
dtype: int32
# 方法二:tail(n)获取后n个元素
s.tail(2) # I 28
J 14
dtype: int32
# 方法三:检测空值
s.isnull()
s.notnull()
pd.isnull(obj)
pd.notnull(obj)
# 方法四:排序
s1.sort_values() # B 2
F 2
C 3
E 3
A 4
D 8
dtype: int32
s1.sort_index() # A 4
B 2
C 3
D 8
E 3
F 2
dtype: int32
# 方法五:值的个数统计
s1.value_counts() # 3 2
2 2
4 1
8 1
dtype: int64
# 方法六:对值进行去重
s1.unique() # array([4, 2, 3, 8])
# 方法七:any() 判断整个数组中是否至少有一个符合条件。
# 方法八:all() 判断整个数组中是否全部满足条件。
# 方法七:丢弃指定轴的数据
s1.drop(['A','C'])
Series兼容numpy array的运算
Series最重要的⼀个功能是,它会根据运算的索引标签⾃动对⻬数据
s2 = pd.Series(data=np.random.randint(1,10,size=5)) # 0 1
1 1
2 3
3 6
4 2
dtype: int32
s3 = pd.Series(data=np.random.randint(1,10,size=5)) # 0 8
1 8
2 2
3 3
4 1
dtype: int32
#进行运算时,是相同的索引对应的值进行运算
s2+s3 # 0 9
1 9
2 5
3 9
4 3
dtype: int32
s2-s3 # 0 -7
1 -7
2 1
3 3
4 1
dtype: int32
s2*s3 # 0 8
1 8
2 6
3 18
4 2
dtype: int32
# 广播机制
s2 +1 # 0 2
1 2
2 4
3 7
4 3
dtype: int32
两个Series对象可以进行基本的运算,不用形状相同
Series对象和ndarray形状相同可以进行运算
s4 = s2+5 # 0 6
1 6
2 8
3 11
4 7
dtype: int32
s4<10 # 0 True
1 True
2 True
3 False
4 True
dtype: bool
s4.values<10 # array([ True, True, True, False, True])
# 获取值小于10的项
s4.loc[s4<10]
s4.loc[s4.values<10]
DataFrame 是由多种类型的列构成的二维标签数据结构,类似于 Excel 、SQL 表,或 Series 对象构成的字典。DataFrame 是最常用的 Pandas 对象,与 Series 一样,DataFrame 支持多种类型的输入数据:
d.index # RangeIndex(start=0, stop=3, step=1)
d.index.name = ''
d.values # array([[100, 48, 88],
[ 50, 69, 47],
[ 60, 40, 95]], dtype=int64)
d.columns # Index(['python', 'java', 'php'], dtype='object')
d.colums.name = ''
d.dtypes # python int64
java int64
php int64
dtype: object
格式:
pd.DataFrame(data=None,index=None,columns=None,dtype=None,copy=False)
如果传入的列在数据中找不到,会自动用NAN补齐
# 方式一:通过numpy的array对象创建
p = pd.DataFrame(data=np.random.randint(40,100,size=(5,3)),index=('a','b','c','d','e'),columns=('python','java','php'))
#
python java php
a 47 49 98
b 82 56 42
c 56 87 99
d 49 41 78
e 58 41 62
# 方法二: 通过字典创建
dict1 = {'python':[100,50,60],
'java':[48,69,40],
'php':[88,47,95]}
d = pd.DataFrame(data=dict1)
# python java php
0 100 48 88
1 50 69 47
2 60 40 95
# 此方式字典的values必须为一维array数组、列表、series一维数组
嵌套字典传给DataFrame,pandas就会被解释为:外层字典的键作为列,内层键则作为⾏索引
# 方法三:通过传递一个 numpyarray,时间索引以及列标签来创建一个DataFrame
dates = pd.date_range('20130101', periods=6)
df = pd.DataFrame(np.random.randn(6,4), index=dates, columns=list('ABCD'))
# 索引
d2 = pd.DataFrame(data=np.random.randint(1,100,size=(4,3)),columns=('python','java','php'),index=('lucy','tony','jack','mark'))
#
python java php
lucy 6 99 89
tony 46 5 58
jack 67 28 3
mark 61 19 79
# 获取某列
d2['python']
d2.python 这种方式不适用于所有的列
它返回Series对象,并且拥有原DataFrame对象的索引,并且name也被设为python
# 获取某几列
d2[['python','php']]
d2.loc[:,['python','php']]
# 获取某几行某几列
d2.loc[['lucy','jack'],['python','php']]
# 获取一个元素
d2.loc['mark','php']
# bool列表的访问
d2.loc[[True,False,False,False]] # 获取第一行
d2.drop(['tony','jack','mark'])
d2[[True,False,False,False]] # 获取第一行
d2.loc[:,[True,False,True]] # 获取一三列
# 切片
d2[0:2] # 获取第一二行
d2.iloc[0:2] # 获取第一二行
# Index 对象
index对象是不可变的,可以使Index对象在多个数据结构之间安全共享
Index的功能也类似⼀个固定⼤⼩的集合
pandas的Index可以包含重复的标签
# 与一个数的运算,运用广播机制
d2+1 # 所有数+1
# 与numpy array数组的运算
arr = np.ones(3,dtype=int) # [1,1,1]
arr+d2
# python java php
lucy 7 100 90
tony 47 6 59
jack 68 29 4
mark 62 20 80
# 与Series对象运算
s = pd.Series(data=[1,2,3],index=['python','java','php'])
d2+s
# python java php
lucy 7 101 92
tony 47 7 61
jack 68 30 6
mark 62 21 82
默认情况下,DataFrame和Series之间的算术运算会将Series的索引匹配到DataFrame的列,然后沿着⾏⼀直向下⼴播
如果你希望匹配⾏且在列上⼴播,则必须使⽤算术运算⽅法
方法名 | 描述 |
---|---|
df.describe() | 数据的快速统计汇总 |
df.T | 数据的转置 |
df.sort_index() | 按轴进行排序 |
df.sort_values() | 按值进行排序 |
df.reindex(index,method,fill_value) | 创建一个数据符合新索引的新对象 |
df.drop() | 丢弃指定轴的数据 |
df.add(df1,fill_value) | 将两个df对象相加,缺失值用指定数代替 |
df.sub() | 两个df对象之差 |
df.apply(f) | 将函数应⽤到由各列或⾏所形成的⼀维数组上 |
逐块读取文件:
读取几行可以使用nrows参数
逐块读取需要指定chunksize参数,返回一个TextParse对象,用于迭代。它有一个get_chunk方法,使我们可以读取任意大小的数据块
import pymysql
conn = pymysql.connect(host='127.0.0.1',port=3306,user='tyl',password='tyl',db='mydb')
sql='select * from department'
pd.read_sql(sql,conn)
conn.close()
2.9.1 分组操作格式:
分组的一般模式:
df.groupby(分组依据)[数据来源].使用操作
多维度分组(根据列名分组 )
df.groupby(['分组依据1','分组依据2',...])[数据来源].使用操作
根据复杂逻辑分组:
df.groupby(condition)[数据来源].使用操作
查看分组类别:
df.drop_duplicates()
2.9.2 groupby对象
改对象本身不会返回什么,只有调用方法后才会起作用
属性:
属性名 | 描述 |
---|---|
ngroups | 查看分组个数 |
groups | 返回组名映射到组索引列表的字典 |
size | 统计每个组的元素个数 |
ngroups | 返回组数 |
方法:
方法名 | 描述 |
---|---|
get_group(name, obj=None) | 获取该组所在的行即,使用提供的名称从组构造DataFrame。 |
head() | 返回每个组的前几行 |
first() | 返回以分组为索引的每组的第一个分组信息 |
2.9.3 分组三大操作‘
聚合函数:
根据返回标量值原则,常见的聚合函数有:
max、min、mean、median中位数、count不统计NAN值、size统计元素个数,包含NAN值、all、any、idxmax、idxmin、mad、nunique去重再计数、skew、quantile、sum、std、var、sem、prod
agg方法:
groupby对象其他函数的缺点:
∙ \bullet ∙ 无法同时使用多个函数
∙ \bullet ∙ 无法对特定的列使用特定的聚合函数
∙ \bullet ∙ 无法使用自定义的聚合函数
∙ \bullet ∙ 无法对结果的列名在聚合前进行自定义命名
agg方法克服了上述的四个缺点:
① 使用多个函数
gb.agg(['函数1','函数2','函数3',.....])
此时返回的列索引为多级索引,第一层为数据源,第二层为聚合函数
② 对特定的列使用特定的聚合函数
gb.agg({'列1':'聚合函数1','列2':['聚合函数2','聚合函数3']})
通过向agg方法的参数中传入字典实现,字典的键为列名,值为聚合函数
③ 使用自定义函数
gb.agg(lambda 变量:条件)
需要注意传入函数的参数是之前数据源的列,逐列计算
④ 聚合结果重命名
gb.agg([('新名字','聚合函数1'),('新名字','聚合函数2')])
变换:
返回一个Series对象,与原序列同长度
常用的内置变换函数为累计函数:cumsum、cumcount、cumprod、cummax、rank
自定义变换使用transform方法,参数为自定义函数还可以为聚合函数
过滤:
fliter函数
filter函数是用来筛选某些组的(务必记住结果是组的全体),因此传入的值应当是布尔标量
2.9.4 跨列分组
函数名 | 描述 |
---|---|
cut( ) | 将值归为离散间隔。 |