tags:Python
一、Pandas基础
1、Pandas简介
Pandas是一个开源的,BSD许可的库,为Python编程语言提供了高性能,易于使用的数据结构和数据分析工具
2、Pandas基本数据结构-Series
Series是一种类似于一维数组的对象,它由一组数据(合种Numpy数据类型)以及一组与之相关的数据标签组成。仅由一组数据即可产生最简单的Series
#pandas中的Series数据类型,相当于一维数组
obj = Series(["貂蝉" ,"西施" ,"杨玉环" ])
obj
0 貂蝉
1 西施
2 杨玉环
dtype: object
#查看数据类型
type (obj )
pandas .core.series.Series
#分别查看Series的元素和索引
#获取元素值
obj.values
array(['貂蝉' , '西施' , '杨玉环' ], dtype=object)
list (obj.index)
[0 , 1 , 2 ]
#获取Series中元素的方式
obj[0 ]
'貂蝉'
#获取多个
obj[[1,2]]
1 西施
2 杨玉环
dtype: object
#创建Series的第二种方法:通过字典创建
#通过字典创建Series,字典的key将作为Series的索引(index),字典value将作为Series的value
price={"貂蝉" :18888 ,"西施" :16888 ,"杨玉环" :19888 }
heroPrice = Series(price)
heroPrice
貂蝉 18888
西施 16888
杨玉环 19888
dtype: int64
#获取索引
heroPrice.index
Index(['貂蝉' , '西施' , '杨玉环' ], dtype='object' )
#获取价格
heroPrice.values
array([18888 , 16888 , 19888 ], dtype=int64 )
#指定Series的索引
price={"貂蝉" :18888 ,"西施" :16888 ,"杨玉环" :19888 }
#给定的index列表中的元素一定是price中的key
heroPrice = Series(price,index=["貂蝉" ,"西施" ,"杨玉环" ])
heroPrice
貂蝉 18888
西施 16888
杨玉环 19888
dtype: int64
3、Pandas基本数据结构-DataFrame
DataFrame是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔值等)。DataFrame既有行索引也有列索引,它可以被看做由Series组成的字典(共用同一个索引)。跟其他类似的数据结构相比(如R的dataframe),Dataframe中的面向行和面向列的操作基本上是平衡的。其实,DataFrame中的数据是以一个或多个二维块存放的(而不是列表、字典或别的一维数据结构)
4、可用于构造DataFrame的数据
类型 说明 二维ndarray 数据矩阵,还可以传入行标和列标 由数组、列表或元祖组成的字典 每个序列会变成DataFrame的一列。所有序列的长度必须相同 Numpy的结构化/记录数组由Series组成的字典 类似于“由数组组成的字典” 由Series组成的字典 每个Series会成为一列。如果没有显示指定索引,则各Series的索引会被合并成结果的行索引 由字典组成的字典 各内层字典会成为一列。键会被合并成结果的行索引,跟“由Series组成的字典”的情况一样 字典或Series的列表 各项将会成为DataFrame的一行。字典键或Series索引的并集将会成为DataFrame的列标 由列表或元祖组成的列表 类似于“二维ndarray” 另一个DataFrame 该DataFrame的索引将会被沿用,除非显式指定了其他索引 Numpy的MaskedArray 类似于“二维ndarray”的情况,只是掩码值在结果DataFrame会变成NA/缺失值
#创建DataFrame数据结构
citypop = {"城市" :["上海" ,"北京" ,"南京" ],
"年份" :[2015 ,2016 ,2017 ],
"人口" :[0.9 ,1.2 ,0.8 ]}
citypop
{'城市' : ['上海' , '北京' , '南京' ], '年份' : [2015 , 2016 , 2017 ], '人口' : [0.9 , 1.2 , 0.8 ]}
#通过字典创建DataFrame,字典的key值作为DataFrame的列名,字典的value作为DataFrame的列数据
df = DataFrame(citypop)
df
list (df.index)
[0 , 1 , 2 ]
#获取DataFrame的列索引
df.columns
Index(['城市' , '年份' , '人口' ], dtype='object' )
#创建DataFrame并指定列名columns
df = DataFrame(citypop,columns=["城市" ,"年份" ,"人口" ])
df
#DataFrame数据的获取
#获取列数据
#df["城市"]
df.年份#获取一列数据
0 2015
1 2016
2 2017
Name: 年份, dtype: int64
#获取多列数据
df[["城市","人口"]]
#获取行数据
df[0 :2 ]
df[0:2 ][["城市","年份" ]]
#向DataFrame新增一列
df["GDP" ] = [8000 ,7500 ,7200 ]
df
#通过Series向DataFrame新增一列数据
area = Series([3000 ,6000 ,4500 ])
area
df["面积" ] = area
df
#通过已存在的列数据产生一列新的数据
#给出一列数据,标注该行对应的城市人口是否大于一亿
df["一亿" ]=df["人口" ]>1.0
df
del df["一亿" ]
df
#创建DataFrame的第二种方法,字典嵌套字典
pop = {"上海" :{2015 :0.6 ,2016 :0.8 ,2017 :1.0 },
"北京" :{2015 :1.7 ,2016 :0.85 ,2017 :1.1 }}
,,,
外层字典的key作为DataFrame的列名
内层字典的key作为Frame的行索引
,,,
citypop = DataFrame(pop)
#将DataFrame的行和列倒置
citypop.T
#通过values方法获取DataFrame的所有值
citypop.values
array([[0.6 , 1.7 ],
[0.8 , 0.85],
[1. , 1.1 ]] )
二、Pandas进阶
1、Series和DataFrame中的索引
pandas的索引对象负责管理轴标签和其他元数据(比如轴名称等)。构建Series或DataFrame时,所用到的任何数组或其他序列的标签都会被转换成一个index index对象是不可修改的(immutable),因此用户不能对其进行修改
pop = {"上海" :{2015 :0 .6 ,2016 :0 .8 ,2017 :1.0 },
"北京" :{2015 :1.7 ,2016 :0 .85 ,2017 :1.1 },
"南京" :{2015 :1.8 ,2016 :0 .95 ,2017 :1.2 }}
citypop = DataFrame(pop )
citypop
nanjing = citypop["南京" ]
type(nanjing)
pandas.core.series.Series
index = nanjing.index
index
Int64Index([2015 , 2016 , 2017 ], dtype='int64' )
index [1 :] #得到的index的索引是不可以修改的
Int64Index([2016 , 2017 ], dtype='int64' )
#data = DataFrame(np.arange(16 ))
,,,
np.arange(start,end,stop)
start: 开始位置 默认起始位置是0
end: 结束位置
step: 步长 默认步长是1
,,,
array([ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15 ])
result = np.arange(start=0 ,stop=20 ,step=4 )
result
array([ 0 , 4 , 8 , 12 , 16 ])
np.arange(16 ).reshape(4 ,4
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]] )
arr = np.arange(16 ).reshape(4 ,4 )
arr
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15]] )
2、索引的删除
#如何删除行和列
del data [2018]
data
#删除多列
data .drop([2015,2017],axis =1)
data
#删除多行
#axis=0或不传入则是删除行
data.drop(["北京" ,"重庆" ],axis=0 )
3、索引的选取和过滤
#索引的过滤
obj = Series(np.arange(4 ),index=["a" ,"b" ,"c" ,"d" ])
obj
a 0
b 1
c 2
d 3
dtype: int32
obj[["a","d"]]
a 0
d 3
dtype: int32
mask = obj>1
mask
a False
b False
c True
d True
dtype: bool
obj [mask]
c 2
d 3
dtype : int32
4、索引的切片选取数据
利用标签的切片运算和普通的Python切片运算不同,其末端是包含的
#切片
#闭区间
obj["b" :"d" ]
b 1
c 2
d 3
dtype: int32
5、DataFrame的索引选项
类型 说明 obj[val] 选取DataFrame的单个列或一组列。在一些特殊情况下会比较便利:布尔型数组(过滤行)、切片(行切片)、布尔型DataFrame(根据条件设置值) obj.ix[val] 选取DataFrame的单个行或一组行 obj.ix[:,val] 选取单个列或列子集 obj.ix[val1:val2] 同时选取行和列 reindex方法 将一个或多个轴匹配到新索引 xs方法 根据标签选取单列或单行,并返回一个Series icol、irow方法 根据整数位置选取单列或单行,并返回一个Series get_value、set_value方法 根据标签和列标签选取单个值
6、pandas中的数据运算与算术对齐
pandas最重要的一个功能是它可以对不同索引的对象进行算术运算。在将对象相加时,如果存在不同的索引对,则结果的索引就是该索引对的并集
s1 = Series([2.3 ,1.5 ,4.5 ,6 ],index=list ("abcd" ))
s2 = Series([1 ,2 ,3 ,4 ,5 ],index=list ("acefg" ))
s1
a 2.3
b 1.5
c 4.5
d 6.0
dtype: float64
s2
a 1
c 2
e 3
f 4
g 5
dtype: int64
s1+s2
a 3.3
b NaN
c 6.5
d NaN
e NaN
f NaN
g NaN
dtype: float64
#DataFrame中数据相加
df1 = DataFrame(np.arange (9 ).reshape (3 ,3 ),
columns=list("bcd" ),
index=["江苏" ,"浙江" ,"湖南" ])
df1
df2 = DataFrame(np.arange (12 ).reshape (4 ,3 ),
columns=list("bde" ),
index=["广东" ,"江苏" ,"山东" ,"湖南" ])
df2
df1.add (df2,fill_value=0 )
df1.add (df2).fillna (0 )
df1 = DataFrame(np.arange (12 ).reshape (3 ,4 ),columns=list("abcd" ))
df1
df2 = DataFrame(np.arange (20 ).reshape (4 ,5 ),columns=list("abcde" ))
df2
#e列和3行就是df2的数据,df1全部填充为0
df1.add(df2,fill_value=0 )
#DataFrame与Series算术运算的广播机制
df1 = DataFrame(np.arange (12 ).reshape (4 ,3 ),
columns=list("bcd" ),
index=["江苏" ,"浙江" ,"湖南" ,"广东" ])
df1
firstRow = df1.loc["江苏" ]
firstRow
#将DataFrame的每一行对应于Series对应的列进行相减,再按照行的方向向下广播
df1-firstRow
7、函数应用和映射
#abslute 取绝对值操作
np .abs ([-1,-4,2,4,-6] )
array ([1, 4, 2, 4, 6] )
#生成一个4行3列的随机数组
df = DataFrame(np.random .randn (4 ,3 ),columns=list("bde" ))
df
frame = df
frame
#修改frame的行索引
frame.index = ["2012" ,"2013" ,"2014" ,"2015" ]
frame
f = lambda x :x.max ()-x.min ()
result = frame.apply(f)
result
frame.apply(f,axis=1 )
#对DataFrame中所有数据进行某一个操作
frame
#对Frame中的数据统一只保留两位小数并转化为字符串
myformat = lambda floatNum : "%.2f" %floatNum
#查看frame中每一列数据的数据类型
frame.dtypes
#可以对Series数据结构进行map操作
frame["e" ].map(myformat)
8、排序和排名
根据条件对数据集排序(sorting)也是一种重要的内置运算。要对行或列索引进行排序按字典顺序,可使用sort_index方法,它将返回一个已经排序的新对象
排序
obj = Series (range(4 ),index=list("dabc" ))
obj
Out [2 ]:
d 0
a 1
b 2
c 3
dtype: int64
#对Series按照索引进行排序
obj.sort_index()
a 1
b 2
c 3
d 0
dtype: int64
#DataFrame中数据的排序
frame = DataFrame(np.arange (8 ).reshape (2 ,4 ),
index=["three" ,"one" ],
columns=list("dabc" ))
frame
#将DataFrame按照行进行排序
frame.sort_index()
#按照列进行排序,默认是升序
frame.sort_index(axis=1 )
#按照降序排序ascending(上升地)
frame.sort_index(axis=1 ,ascending =False)
排名
students = {"数学" :[89 ,94 ,75 ,78 ],
"英语" :[88 ,90 ,75 ,89 ]}
scores = DataFrame(students)
scores.sort_values(by ="数学" )
scores.sort_values(by ="英语" )
scores.sort_values(by =["数学" ,"英语" ])
9、带有重复值的轴索引
obj = Series(range(5 ),index=list("aabbc" ))
obj
a 0
a 1
b 2
b 3
c 4
dtype: int64
obj.index.is_unique
False
obj["a" ]
a 0
a 1
dtype: int64
10、汇总计算描述统计
df = DataFrame({"Java" :[90 ,80 ,75 ],
"Python" :[78 ,88 ,98 ],
"Go" :[98 ,75 ,85 ]})
df.index = ["小明" ,"小强" ,"小红" ]
df
#对DataFrame中的数据求和,默认按照列方向求和
df.sum ()
df.loc ["求和" ] = df.sum ()
df
#按照行方向求和
df.sum(axis=1 )
小明 266
小强 243
小红 258
求和 767
dtype: int64
#求每个学生成绩总和
df["总分" ] = df.sum(axis=1 )
df
df.sort_values(by ="总分" ,ascending = False)
#数据中出现先缺失值的时候
df2 = DataFrame({"Java" :[90 ,80 ,75 ],
"Python" :[78 ,np.nan ,98 ],
"Go" :[np.nan ,75 ,85 ]})
df2.index = ["小明" ,"小强" ,"小红" ]
df2
#如果说数据中出现缺失值,则自动省略
df2.sum ()
Java 245.0
Python 176.0
Go 160.0
dtype: float64
#按照列方向求平均,并且不省略NaN 值
df2.mean(axis=0 ,skipna=False)
Java 81.666667
Python NaN
Go NaN
dtype: float64
#按照行方向求平均,并且省略NaN值
df2.mean (axis=1 ,skipna=True)
小明 84.0
小强 77.5
小红 86.0
dtype: float64
df2["平均分" ] = df2.mean(axis=1 ,skipna=True )
df2
obj2 = Series([1 ,2 ,3 ,4 ,5 ,2 ])
#自动根据Series中的数据类型统计不同的结果
obj2.describe ()
Out [45 ]:
count 6.000000
mean 2.833333
std 1.471960
min 1.000000
25 % 2.000000
50 % 2.500000
75 % 3.750000
max 5.000000
dtype: float64
11、唯一值、值计数与成员资格
方法 适用对象 unique函数 从一组数中抽取唯一值 uniques.sort() 返回的值是无序的,需要进行排序 value_counts 计算一个Series中各值出现的频率,默认情况下,Series统计出来的值是按降序排列的 value_counts顶级方法(见下方序号1) 用于任何的数组和序列
#统计出Series中所有不重复的元素有哪些
obj.unique()
array(['a' , 'b' , 'c' ], dtype=object)
#去除重复项
set = {"a" ,"b" ,"c" ,"a" ,"b" }
set
{'a' , 'b' , 'c' }
#统计Series每个元素出现的次数
obj.value_counts()
a 8
c 4
b 4
dtype: int64
(1 )调用pandas中顶级api的value_counts方法
pd.value_counts(obj,sort =True)
a 8
c 4
b 4
dtype: int64
#判断Series 中每个元素是否在某个集合中
mask = obj.isin(["b" ,"c" ])
mask
0 False
1 False
2 True
3 True
4 False
5 False
6 True
7 True
8 False
9 False
10 True
11 True
12 False
13 False
14 True
15 True
dtype: bool
#通过花式索引提取所有Series 中数据属于列表["b" ,"c" ]的子集元素
obj[mask]
Out [64 ]:
2 b
3 c
6 b
7 c
10 b
11 c
14 b
15 c
dtype: object
12、缺失值处理
缺失数据(missing data)在大部分数据分析应用中都很常见。pandas的设计目标之一就是让缺失数据的处理任务尽量轻松。例如:pandas对象上的所有描述统计都排除了缺失数据 pandas内置的none值也会当做缺失值处理
NA处理方法
方法 说明 dropna 根据各标签的值中是否存在数据对轴标签进行过滤,可通过阀值调节对缺失值的容忍度 fillna 用指定值或插值方法(如ffill或bfill)填充缺失数据 isnull 返回一个含有布尔值的对象,这些布尔值表示哪些值是缺失值/NA,该对象的类型与源类型一样 notnull isnull的否定式
data = DataFrame({"Qu1" :[1 ,3 ,4 ,3 ,4 ],
"Qu2" :[2 ,3 ,1 ,2 ,3 ],
"Qu3" :[1 ,5 ,2 ,4 ,4 ]})
data
#统计data中每一列中每个元素出现的次数
#fillna(0)把所有Nan值填充为0
data .apply(pd .value_counts ) .fillna(0)
#缺失值处理
names = Series(["小强" ,"小红" ,np.nan ,"小明" ])
names
0 小强
1 小红
2 NaN
3 小明
dtype: object
names.isnull()
0 False
1 False
2 True
3 False
dtype: bool
#判断元素是否不为空值
mask = names.notnull()
#提取Series中不为空的所有元素
names[mask]
0 小强
1 小红
3 小明
dtype: object
names
0 小强
1 小红
2 NaN
3 小明
dtype: object
#删除names中的Nan值
names.dropna ()
0 小强
1 小红
3 小明
dtype: object
#DataFrame中的缺失值处理
cols = {"a" :[1 ,6.5 ,3 ],
"b" :[1 ,2.3 ,np.nan],
"c" :[np.nan,3.3 ,np.nan],
"d" :[np.nan,6.5 ,3 ]}
data = DataFrame (cols )
data
#删除data中的缺失值
#默认删除出现了Nan的行数据
data .dropna()
#只删除全为Nan的行
cols = {"a" :[np.nan ,6.5 ,3 ],
"b" :[np.nan ,2.3 ,np.nan ],
"c" :[np.nan ,3.3 ,np.nan ],
"d" :[np.nan ,6.5 ,3 ]}
data = DataFrame(cols)
data.dropna (how="all" )
data
#指定只删除列或者行方向上出现的Nan的数据
data2 = DataFrame({"key1" :[1 ,2 ,3 ,4 ],
"key2" :[np.nan ,np.nan ,np.nan ,np.nan ]})
data2
#默认axis=0,只删除全为Nan的列数据
data2.dropna (axis=1 )
13、填充缺失数据
我们在操作程序时可能不想滤除缺失数据(有可能会丢弃跟它有关的其他数据),而是希望通过其他方式填补那些空洞。对于大部分情况而言,fillna方法是最主要的函数。通过一个常数调用fillna就会将缺失值替换为那个常数值 若是通过一个字典调用fillna,可以实现对不同列填充不同的值
#填充缺失值
data2.fillna (0 )
data2["key3" ] = [5 ,np.nan ,7 ,np.nan ]
data2
#通过字典可以指定对不同列中的Nan值填充不同的值,不改变原始数据
data2.fillna({"key2" :0 ,"key3" :888 })
#填充缺失值并且改变原始数据
#inplace=True代表修改原始数据
#inplace=Flase代表不改变原始数据
data2.fillna(888 ,inplace=True)
data2