1 Pandas 的介绍和安装
(1)为什么会有Pandas?
Pandas支持大部分Numpy语言风格,尤其是数组函数与广播机制的各种数据处理。但是Numpy更适合处理同质型的数据。而Pandas的设计就是用来处理表格型或异质型数据的,高效的清洗、处理数据。
(2)Pandas是什么?
Pandas是基于Numpy的一种工具,提供了高性能矩阵的运算,该工具是为了解决数据分析任务而创建的。也是贯穿整个Python数据分析非常核心的工具。
(3)Pandas涉及内容
(4)Pandas安装
直接在dos命令行中输入pip install pandas
。
2 Pandas中Series的数据结构介绍
2.1 Series的介绍
Series是一种一维的数组型对象,它包含了一个值序列(values),并且包含了数据标签,称为索引(index),本质相当于一列数据。
2.2 Series的创建
语法:pd.Series(data=None,index=None,dtype=None,name=None,copy=False)
- data:创建数组的数据,可为array-like, dict, or scalar value
- index:指定索引
- dtype:数组数据类型
- name:数组名称
- copy:是否拷贝
- 注意:data可为iterable, dict, or scalar value
"""data为iterable"""
s1 = pd.Series([1,2,3,4],index=['a','b','c','d'],name='example')
print(s1)
"""注意1:pandas里面索引是可重复的"""
s2 = pd.Series([1,2,3,4,5],index=list("aacde"))
print(s2)
"""注意2:索引的个数与data的个数是否要一致?index与values的个数必须一致"""
# s3 = pd.Series([1,2,3,4,5],index=list("aabcde"))
# print(s3) # 报错
"""data为字典,key对应索引,value对应值"""
dic1 = {"name":"steven","age":18,"gender":"male"}
s4 = pd.Series(dic1)
print(s4)
# 构建索引列表
dic2 = {"name":"steven","age":18,"gender":"male"}
index_li = ["class","name","gender"]
s5 = pd.Series(dic2,index=index_li) # 以index指定的索引列表为主 class 在dic2 中没有,以nan形式填充
print(s5)
"""data为向量scalar"""
s6 = pd.Series(np.random.randint(1,10,size=5),dtype="float")
print(s6) # 查看类型
除此之外,Pandas可以使用Numpy的数组函数
- s.dtype :查看数据类型
- s.astype():修改数据类型
- s.head(n) :预览数据前5条
- s.tail(n) :预览数据后5条
但是如果需要显示所有数据,则需以下代码。但并不建议使用
`#显示所有列
pd.set_option('display.max_columns', None)
#显示所有行
pd.set_option('display.max_rows', None)
#设置value的显示长度为100,默认为50
pd.set_option('max_colwidth',100)
2.3 Series的索引与切片
2.3.1 Series的索引与值
- s.index : 查看索引
- s.values:查看值序列
- s.reset_index(drop=False):重置索引
- drop :是否删除原索引 默认为否
- 注意 :索引对象是不可变的,所以不能单个修改索引
s1 = pd.Series(np.arange(5))
s2 = pd.Series(['a','b','c'],index=['A','B','C'])
print(s1,s2)
print(s1.index,type(s1.index),s2.index,type(s2.index))
print(s1.values,type(s1.values),s2.values,type(s2.values))
# 获取索引A 注意:不是s2["A"] 这样是取值的
print(s1.index[1])
print(s2.index[1])
# print(s2.index['A']) # 报错
# 是否可以修改单独的索引?
# s2.index[1] = "D" # 报错:注意:索引对象是不可变的,为了更安全
2.3.2 Series的索引与切片
- s[‘标签’]: 通过标签
- s[‘索引’] :通过索引
- s.loc[标签] : 通过标签
- s.iloc[索引]:通过索引
s1 = pd.Series(np.arange(1,6),index=list("abbde"))
print(s1)
# 取2
print(s1["b"],'\n','----------------') # 通过标签
print(s1[1],'\n','----------------') # 通过索引
print(s1.loc["b"],'\n','----------------') # 通过标签
print(s1.iloc[1],'\n','----------------') # 通过索引
# 查看 "a","d"
print(s1[["a","d"]],'\n','----------------') # 通过标签
print(s1[[0,3]],'\n','----------------') # 通过索引
# 取大于3的值 布尔索引
print(s1[s1>3],'\n','----------------')
# pandas 会根据数据类型 自动的处理缺失数据
data = ["a","b",None]
print(pd.Series(data),'\n','----------------') # object
data = [1,2,None]
print(pd.Series(data),'\n','----------------') # np.nan 浮点类型 float64
2.4 Series 的运算
- 共同索引对应为运算,其它填充NaN
- 没有共同索引时,则全部为NaN
"""共同索引对应为运算,其它填充NaN"""
s1 = pd.Series(np.arange(10,20),index=range(10))
s2 = pd.Series(np.arange(20,25),index=range(5))
print(s1,'\n','----------------')
print(s2,'\n','----------------')
print(s1+s2,'\n','----------------')
"""没有共同索引时,则全部为NaN"""
s3 = pd.Series(np.arange(5),index=range(5))
s4 = pd.Series(np.arange(5,10),index=range(5,10))
print(s3,'\n','----------------')
print(s4,'\n','----------------')
print(s3+s4,'\n','----------------')
3 Pandas中DataFrame的数据结构介绍
3.1 DataFrame介绍
DataFrame表示的是矩阵的数据表,它包含已排序的列集合,每一列可以是不同的值类型(数值,字符串,布尔值)。在DataFrame中,数据被存储为一个以上的二维块。
3.2 DataFrame创建
pd.DataFrame(data=None,index=None,columns=None,dtype=None,copy=False)
- data:创建数组的数据,可为ndarray, dict
- index:指定索引
- dtype:数组数据类型
- copy:是否拷贝
d1 = pd.DataFrame(np.random.randint(1,100,size=(3,3)))
print(d1,'\n','-------------------------------------------------')
"""
行索引 index 0轴 axis=0
列索引 columns 1轴 axis=1
值 values
"""
print(d1.index,'\n','-------------------------------------------------') # RangeIndex
print(d1.columns,'\n','-------------------------------------------------') # RangeIndex
print(d1.values,'\n','-------------------------------------------------') # ndarray的二维数组
# 指定index 为["amy","mia","steven"]
# 指定columns 为["java","python","R"]
d2 = pd.DataFrame(np.random.randint(1,100,size=(3,3)),index=["amy","mia","steven"],columns=["java","python","R"])
print(d2,'\n','-------------------------------------------------')
"""
字典形式的data(同Seires)
- key值为列索引
- value为值
- 行索引 不指定就为默认的
"""
data = {
"name":["amy","mia","steven"],
"lesson":["java","python","R"]
}
d3 = pd.DataFrame(data)
print(d3,'\n','-------------------------------------------------')
# 指定一下列索引
d4 = pd.DataFrame(data,columns=["lesson","name"])
print(d4,'\n','-------------------------------------------------')
# 以我们指定的columns为主
d5 = pd.DataFrame(data,columns=["lesson"])
print(d5,'\n','-------------------------------------------------')
# 以我们指定的columns为主 指定的 多于 data的key值时,则会填充nan
d6 = pd.DataFrame(data,columns=["lesson","name","age"]) # age 不存在,填充为nan
print(d6,'\n','-------------------------------------------------')
# 字典数据结构不一致的 也会补齐为nan
data1 = [
{"name":"amy","age":18,"gender":1},
{"name":"jun","age":20},
{"name":"hy","gender":1}
]
d7 = pd.DataFrame(data1)
print(d7,'\n','-------------------------------------------------')
"""
重置索引:
除了创建时可以指定,我们创建后还可以通过df.reindex()进行重置索引
语法:df.reindex(index=None, columns=None, axis=None,fill_value=nan)
"""
df = pd.DataFrame(np.arange(9).reshape(3,3),index=list("abc"),columns=list("ABC"))
print(df,'\n','-------------------------------------------------')
# 重置行索引
df1 = df.reindex(index=[1,2,3]) # 如果重置的索引 与 df中指定的index 无关系 则全部填充nan
print(df1,'\n','-------------------------------------------------')
df2 = df.reindex(index=["b","c","a"]) # 如果重置索引与df指定的索引 完全一致 但是乱序的话 根据重置索引变动
print(df2,'\n','-------------------------------------------------')
df3 = df.reindex(index=["b","c","a","d"]) # 如果重置索引 比 df指定的索引 多 则多出的部分填充nan
print(df3,'\n','-------------------------------------------------')
# 填充列索引
df4 = df.reindex(columns=list("BCA")) # 跟行索引一样的本质一样,有就排序,没有就填充nan
print(df4,'\n','-------------------------------------------------')
# 同时重置
df5 = df.reindex(index=list("bca"),columns=list("CBA"))
print(df5,'\n','-------------------------------------------------')
3.3 DataFrame基础操作
- df.shape :查看数组形状,返回值为元组
- df.dtypes :查看列数据类型
- df.ndim :数据维度,返回为整数
- df.index :行索引
- df.columns :列索引
- df.values :值
- d.head(n) :显示头部几行,默认前5行
- d.tail(n) :显示末尾几行,默认后5行
- d.info() :相关信息概述
data = [
{"name":"amy","age":18,"tel":10086},
{"name":"bob","age":18},
{"name":"james","tel":10086},
{"name":"zs","tel":10086},
{"name":"james","tel":10086},
{"name":"ls","tel":10086},
]
d1 = pd.DataFrame(data)
print(d1,'\n','-------------------------------------------------')
print(d1.shape,'\n','-------------------------------------------------') # 查看数组形状 (6,3) 六行三列 二维的
print(d1.ndim,'\n','-------------------------------------------------') # 查看数组维度 df为二维的
print(d1.dtypes,'\n','-------------------------------------------------') # 查看列的数据类型 注意:每列的类型可以不一致 体现pandas更加灵活
print(d1.head(),'\n','-------------------------------------------------') # 显示前几行 默认为5
print(d1.tail(),'\n','-------------------------------------------------') # 显示末尾几行 默认为5
print(d1.info(),'\n','-------------------------------------------------') # 描述信息概要 Non-Null Count:非NAN数据的次数
3.4 DataFrame的增删改查
3.4.1 DataFrame的查
- 直接使用索引与标签
- 使用loc及iloc查询数据
·df.loc[] 通过轴标签选择数据
·df.iloc[] 通过整数索引选择数据
"""使用索引查询数据"""
data = [
{"name":"amy","age":18,"tel":10086},
{"name":"bob","age":18},
{"name":"james","tel":10086},
{"name":"zs","tel":10086},
{"name":"james","tel":10086},
{"name":"ls","tel":10086},
]
d1 = pd.DataFrame(data,index=list("abcdef"))
print(d1,'\n','-------------------------------------------------')
"""
行索引
"""
# 取前两行
print(d1[:2],'\n','-------------------------------------------------') # 索引
print(d1[:"b"],'\n','-------------------------------------------------') # 标签 []
# d1[["a","b"]] # 报错 这种写法默认为 列索引,所以去列索引中找 没找着,则报错
# d1["a"] # 报错 这种写法默认为 列索引
"""
列索引
"""
# 取 name 这列 字典的本质
print(d1["name"],'\n','-------------------------------------------------') # 取出来单列,会变为Series类型
print(d1.name,'\n','-------------------------------------------------')
print(type(d1["name"]),'\n','-------------------------------------------------') # DataFrame其实是Series容器
# 取 name,tel
print(d1[["name","tel"]],'\n','-------------------------------------------------') # 取两列,取多列仍然时DataFrame
print(type(d1[["name","tel"]]),'\n','-------------------------------------------------')
# 取前两行的 name
print(d1[:2]["name"],'\n','-------------------------------------------------')
# 布尔索引 取出 name 不为james
print(d1[d1["name"]!="james"],'\n','-------------------------------------------------')
"""使用loc及iloc查询数据"""
idx = ["PHP","JAVA","Python","GO"]
col = ["one","two","three","four"]
d2 = pd.DataFrame(np.arange(16).reshape(4,4),index=idx,columns=col)
print(d2,'\n','-------------------------------------------------')
"""
df.loc[行,列]
取单
"""
# 取 Python 这行
print(d2.loc["Python",:],'\n','-------------------------------------------------')
# 取 three 这列
print(d2.loc[:,"three"],'\n','-------------------------------------------------')
"""
df.loc[行,列]
取多行
"""
# 取 PHP 与 GO 这两行
print(d2.loc[["PHP","GO"],:],'\n','-------------------------------------------------')
# 取 PHP 到 GO 这四行
print(d2.loc["PHP":"GO",:],'\n','-------------------------------------------------')
# 取 one four 两列
print(d2.loc[:,["one","four"]],'\n','-------------------------------------------------')
# 取连续行 java~go
print(d2.loc["JAVA":"GO",:],'\n','-------------------------------------------------') # 标签索引可以切片 双闭合
"""
索引位置
df.iloc[行,列]
"""
# 取 Python 这行
print(d2.iloc[2,:],'\n','-------------------------------------------------')
# 取 three 这列
print(d2.iloc[:,2],'\n','-------------------------------------------------')
# 去连续行 java~go
print(d2.iloc[1::,:],'\n','-------------------------------------------------') # 左闭右开
# 取出 one two three数据 并且 筛选出 two列 大于3的
print(d2.loc[:,"one":"three"][d2.two>3],'\n','-------------------------------------------------')
idx = ["PHP","GO","Python","GO"]
col = ["one","two","three","four"]
d3 = pd.DataFrame(np.arange(16).reshape(4,4),index=idx,columns=list("1234"))
print(d3,'\n','--------------------------------------------')
# print(d3.loc["PHP":"GO",:]) # 报错
"""
注意:如果 出现了重复索引 然后切片时出现歧义则会报错
注意:如果列索引 为 1,2,3,4这种就不要使用 d3.1 访问会报错。
"""
### 3.4.2 DataFrame的改
修改数据主要遵循以下两点:
- 查询数据
- 再赋值
注意:Pandas中可以直接赋值np.nan,且赋值当前列数据会自动转为浮点类型。而不是整个数组都转,这主要是因为Pandas数据可以是异质性。
idx = ["PHP","GO","Python","GO"]
col = ["one","two","three","four"]
d4 = pd.DataFrame(np.arange(16).reshape(4,4),index=idx,columns=col)
print(d4,'\n','--------------------------------------------')
# 修改php 整行数据为 8 注意:修改的是原数据
d4.loc["PHP",:] = 8
print(d4,'\n','--------------------------------------------')
# 修改two 整列数据为 10 注意:修改的是原数据
d4.loc[:,"two"] = 10
print(d4,'\n','--------------------------------------------')
# 修改对应python和hree的10改为80
d4.loc["Python","three"] = 80
print(d4,'\n','--------------------------------------------')
# 可以直接赋值为np.nan吗?
d4.loc["Python","three"] = np.nan
print(d4,'\n','--------------------------------------------') # 注意:pandas可以自动转为float
3.4.3 DataFrame的增
- 新增列:df[“新的列标签”] = 值
注意:添加列,则新添加的值的长度必须与其它列的长度保持一致,否则会报错。 - 插入列:如果需要在数据中插入列,则使用 df.insert(loc, column, value)
• loc 为插入列的位置
• column 为插入列的标签
• value 为插入列的值 - 添加行:df.loc[“新的行标签”,:] = 值
- 除此之外,我们还可以通过 df.append(df2) 方法添加行,但类似于数组与数组的堆叠拼接。所以df2的列索引必须同df一致。
"""新增列"""
idx = ["PHP","JAVA","Python","GO"]
col = ["one","two","three","four"]
d5 = pd.DataFrame(np.arange(16).reshape(4,4),index=idx,columns=col)
print(d5,'\n','--------------------------------------------')
# 添加five列 全为10
d5["five"] = 10
print(d5,'\n','--------------------------------------------')
# 重复索引会覆盖原有的信息
d5["five"] = [1,2,3,4]
print(d5,'\n','--------------------------------------------')
# 添加列,则需要保证数组的长度与该列的长度一致
# d5["five"] = [1,2,3] # 报错
# print(d5,'\n','--------------------------------------------')
"""插入列"""
# 在第0列前 插入"six"这列
d5.insert(0,"six",[4,5,76,8])
print(d5,'\n','--------------------------------------------')
"""添加行"""
d5.loc["C++",:] = np.arange(6)
print(d5,'\n','--------------------------------------------')
"""叠加"""
d6 = pd.DataFrame(np.arange(6).reshape(1,6),index=["C"],columns=d5.columns)
d5= d5.append(d6) # 添加行 注意:d6与d5的列索引一致
print(d5,'\n','--------------------------------------------')
3.4.4 DataFrame的删
- 法1:del df[“列标签”]
- 法2:df.drop(axis=0,index=None,columns=None, inplace=False)
d7 = pd.DataFrame(np.arange(9).reshape(3,3),index=list("abc"),columns=list("ABC"))
print(d7,'\n','--------------------------------------------')
# del删除数据
del d7["C"] # 获取到"C"列 删除这列
print(d7,'\n','--------------------------------------------')
# drop 删除数据
d8 = d7.drop(columns="A") # 删除"A"列
print(d8,'\n','--------------------------------------------')
# 删除 "a","c"两行
d9 = d7.drop(index=["a","c"])
print(d9,'\n','--------------------------------------------')
# 指定轴来控制 行与列
d10 = d7.drop("b",axis=0)
print(d10,'\n','--------------------------------------------')
d11= d7.drop("A",axis=1)
print(d11,'\n','--------------------------------------------')
3.5 DataFrame的合并
3.5.1 pd.concat
语法:df = pd.concat(objs, axis = 0, ignore_index = False, join = "outer
(1)concat是”contatenate"的缩写,指的是多表之间的“拼接”。事实上“拼接”和“合并”还是有区别的,拼接一般是上下,合并时左右。
(2)参数解释:
- objs: 指的是要合并的dataframe(们)。可以是一个列表[df1,df2,…]也可以是一个集合(df1,df2,…)。
- axis:指的是拼接的方向。axis = 0指的是拼接行(向下拼接),axis = 1指的是拼接列(向右拼接)。
- ignore_index: 指的是拼接后是否忽视原df各自的索引。比如,假如我们按行拼接,原来df1中有五条数据,索引是0,1,2,3,4。原来的df2中也有五条数据,索引也是0,1,2,3,4。如果我们在合并时,将ignoreindex的值设为False,那么拼接后df的索引就是0,1,2,3,4,0,1,2,3,4。那么如果将ignore_index的值设为True, 那么拼接后df的索引就是0,1,2,3,4,5,6,7…
- join:表示“如何拼接”。由于两表中的信息可能是不同的,所以要设置这个参数以表明拼接方式。其中,outer表示取并集,inner表示取交集。
举例来看一下吧
df1 = pd.DataFrame(np.arange(12).reshape(4,3),index=range(0,4),columns=list('abc'))
df2 = pd.DataFrame(np.arange(12).reshape(4,3),index=range(0,4),columns=list('def'))
print(df1,'\n','--------------------------------------------')
print(df2,'\n','--------------------------------------------')
# df3 = pd.concat([df1,df2],axis=0)
# df3
df4 = pd.concat([df1,df2],axis=1,ignore_index=False)
df4
3.5.2 df.append
语法:df = df1.append(df2)
append可以视作axis=0的,简便版的concat。也就是说,它只支持行拼接,同时比concat简便一些。
- 这里要注意和concat的用法区别。concat是pd的属性,所以调用的时候应该是pd.concat((df1,df2)),而append是对df的方法,所以调用的时候是df1.append(df2)
df1 = pd.DataFrame(np.arange(12).reshape(4,3),index=range(0,4),columns=list('abc'))
df2 = pd.DataFrame(np.arange(12).reshape(4,3),index=range(0,4),columns=list('def'))
print(df1,'\n','--------------------------------------------')
print(df2,'\n','--------------------------------------------')
df3 = df1.append(df2)
df3
3.5.3 pd.merge
语法:df = pd.merge(left, right, how = "inner",on = "None")
与concat(拼接)不同,merge才是真正意义上的”合并“。
- 拼接和合并的区别在于,拼接只是简单地”堆“在一起,而合并则是基于某一个”主键“将两个表”合“在一起。事实上merge也有很多参数,这里只列了最常用的。其中:
- 参数解释:
(1)left: 左表。也就是第一个df。
(2)right:右表。也就是第二个df。
(3)how: 和concat里面的"join"类似,表示“如何合并两表。除了”inner“和”outer“以外,merge中还有”left"(基于左表进行合并)和“right”(基于右表进行合并)。具体地:1)left: 只使用左表的键。2)right:只使用右表的键。3)inner: 使用左右表键的交集。4)outer:使用左右表键的并集。
(4)on: 表示按照哪一个键来进行合并
df1= pd.DataFrame(np.arange(12).reshape(4,3),index=range(0,4),columns=list('abc'))
df2 = pd.DataFrame(np.arange(12).reshape(4,3),index=range(0,4),columns=list('def'))
print(df1,'\n','--------------------------------------------')
print(df2,'\n','--------------------------------------------')
df3 = pd.merge(df1,df2,how='outer',left_index=True,right_index=True)
df3
3.5.4 df.join
语法:df = left.join(right,on = "key", how = "left")
- 类似于append之于concat,join也可以被理解为merge的一个简便并且特殊的方法。join也可以设置参数"how",只不过这里默认值不同。Merge中,how的默认值是”inner“,join中的默认值为”left"。
df1= pd.DataFrame(np.arange(12).reshape(4,3),index=range(0,4),columns=list('abc'))
df2 = pd.DataFrame(np.arange(12).reshape(4,3),index=range(0,4),columns=list('def'))
print(df1,'\n','--------------------------------------------')
print(df2,'\n','--------------------------------------------')
df3 = df1.join(df2,how='right')
df3