Pandas 是基于NumPy 基于 NumPy 构建的含有更高级数据结构和分析能力的工具包,提供了大量能使我们快速便捷地处理数据的函数和方法。
在NumPy中数据结构是围绕ndarray展开的, 那么在Pandas中的核心数据结构是Series和 DataFrame,分别代表着一维的序列和二维的表结构。基于这两种数据结构,Pandas可以对数据进行导入、清洗、处理、统计和输出。
Series对象
Series是Pandas中最基本的对象,代表着一维的序列,类似一种一维数组。和 NumPy的一维的数组不同,Series 能为数据自定义标签,也就是索引(index),然后通过索引来访问数组中的数据。
Series有两个基本属性:index和values,index默认是0,1,2,......递增的整数序列,当然我们也可以用过创建标签,来指定索引,比如index=[‘a’, ‘b’, ‘c’, ‘d’]。
import pandas as pd
from pandas import Series,DataFrame
x1 = Series([1,2,3,4])
x2 = Series(data=[1,2,3,4], index=['a', 'b', 'c', 'd'])
# x2 = Series(data = [1,2,3,4], index = list('abcd')) 指定索引的另一种写法,index赋值一个列表,可以自动分割成四个元素,写法更为方便
print(x1)
print(x2)
# 获取values
print(x2.values)
# 获取索引
print(x2.index)
# 获取索引和值对
print(list(x2.iteritems()))
'''
运行结果:
0 1
1 2
2 3
3 4
dtype: int64
a 1
b 2
c 3
d 4
dtype: int64
x1中的index采用的是默认值,x2中index进行了指定
[1 2 3 4]
Index(['a', 'b', 'c', 'd'], dtype='object')
[('a', 1), ('b', 2), ('c', 3), ('d', 4)]
'''
# 创建字典,转换为Series
dict={"red":100,"black":400,"green":300,"pink":900} # 小提示:字典是python的数据类型,键值对组成
x3=Series(dict)
print(x3)
'''
red 100
black 400
green 300
pink 900
dtype: int64
'''
Series数据获取
import pandas as pd
from pandas import Series,DataFrame
sel = series(data = [1,2,3,4], index = list['abcd'])
print(sel)
# Series对象,同时支持位置和标签两种方式获取数据
print(sel['c']) #标签下标
print(sel[2]) # 位置下标
# 获取不连续的数据
print(sel[['a','c']]) # 标签下标
print( sel[[1,3]]) # 位置下标
# 使用切片获取数据
print(sel[1:3]) # 位置切片,左包含右不包含
print(sel['b':'d'])# 标签切片,左右都包含
# 重新赋值索引的值
sel.index = list('dcba')
print(sel)
# ReIndex重新索引,会返回一个新的Series(调用reindex将会重新排序,缺失值则用NaN填补)
print(sel.reindex(['b','a','c','d','e']))
# Drop丢弃指定轴上的项
se1=pd.Series(range(10,15))
print(se1)
print(se1.drop([2,3]))
Series 进行算术运算操作
对 Series 的算术运算都是基于 index 进行的,我们可以用加减乘除(+ - * /)这样的运算符对两个Series进行运算,Pandas 将会根据索引 index,对相应的数据进行计算,结果将会以浮点数的形式存储,以避免丢失精度。计算时,如果 Pandas在两个Series里找不到相同的 index,对应的位置就返回一个空值 NaN。
import pandas as pd
from pandas import Series,DataFrame
import numpy as np
series1 = Series([1,2,3,4],['London','HongKong','NewYork','Shnghai'])
series2 = Series([1,3,6,4],['London','Accra','Shanghai','Delhi'])
print(series1-series2)
print(series1+series2)
print(series1*series2)
'''
两个Series加减乘除的对象是相同的索引值的对应值进行运算,如果index不对应则返回NaN
Accra NaN
Delhi NaN
HongKong NaN
NewYork NaN
London 0.0
Shanghai -2.0
dtype: float64
Accra NaN
Delhi NaN
HongKong NaN
NewYork NaN
London 2.0
Shanghai 10.0
dtype: float64
Accra NaN
Delhi NaN
HongKong NaN
NewYork NaN
London 1.0
Shanghai 24.0
dtype: float64
'''
# 同样也支持numpy的数组运算
sel = Series(data = [1,6,3,5], index = list('abcd'))
print(sel[sel>3]) # 布尔数组过滤
print(sel*2) # 标量乘法
print(np.square(sel)) #numpy数组的求每个元素的平方的方法
'''
b 6
d 5
dtype: int64
a 2
b 12
c 6
d 10
dtype: int64
a 1
b 36
c 9
d 25
dtype: int64
'''
DataFrame对象
DataFrame(数据框)是一种二维数据结构,数据以表格的形式存储,分成若干行和列。通过 DataFrame,你能很方便地处理数据。常见的操作比如选取、替换行或列的数据,还能重组数据表、修改索引、多重筛选等。
我们基本上可以把 DataFrame 理解成一组采用同样索引的 Series 的集合。调用DataFrame()可以将多种格式的数据转换为DataFrame对象,它的的三个参数data、index和columns分别为数据、行索引和列索引。
DataFrame的创建
import pandas as pd
from pandas import Series,DataFrame
import numpy as np
# 使用二维数组
df1 = DataFrame(np.random.randint(0,10,(4,4)),index=[1,2,3,4],columns=['a','b','c','d'])
# np.random.randint(low,high,size) 生成4行4列的数组,每个元素的取值范围是0-10
print(df1)
'''
a b c d
1 5 7 1 2
2 4 8 5 0
3 3 5 3 2
4 3 8 7 5
'''
# 使用字典创建(行索引由index决定,列索引由字典的键决定)
dict = {
'Province': ['Guangdong', 'Beijing', 'Qinghai', 'Fujian'],
'pop': [1.3, 2.5, 1.1, 0.7],
'year': [2020, 2020, 2020, 2020]}
df2=pd.DataFrame(dict,index=[1,2,3,4])
print(df2)
'''
Province pop year
1 Guangdong 1.3 2020
2 Beijing 2.5 2020
3 Qinghai 1.1 2020
4 Fujian 0.7 2020
'''
# 使用from_dict
dict2 = {"a":[1,2,3],"b":[4,5,6]}
df3 = pd.DataFrame.from_dict(dict2) # 没有指定行索引,则按默认方式
print(df3)
'''
a b
0 1 4
1 2 5
2 3 6
'''
# 索引相同的情况下,相同索引的值会相对应,缺少的值会添加NaN
# 此种情况出现在,将表格中几列数据组合在一起时,部分列多出几行;表格中的一列可以看做一个Series对象
data = {
'Name':pd.Series(['zs','ls','we'],index=['a','b','c']),
'Age':pd.Series(['10','20','30','40'],index=['a','b','c','d']),
'country':pd.Series(['中国','日本','韩国'],index=['a','c','b'])
}
# Age行多了40,索引多了一个’d‘
df4 = pd.DataFrame(data)
print(df4)
'''
Name Age country
a zs 10 中国
b ls 20 韩国
c we 30 日本
d NaN 40 NaN
'''
# to_dict()方法将DataFrame对象转换为字典
dict3 = df4.to_dict()
print(dict3)
'''
{'Name': {'a': 'zs', 'b': 'ls', 'c': 'we', 'd': nan},
'Age': {'a': '10', 'b': '20', 'c': '30', 'd': '40'},
'country': {'a': '中国', 'b': '韩国', 'c': '日本', 'd': nan}}
'''
DataFrame对象常用属性
常用属性可以让我们对对于DataFrame格式中的数据集的数据情况进行描述,得知形状,行值和列索引。
此外我们还要掌握常见的取数方法,取行和列,包括某行某列,连续的行和列,间断的行和列,单个数据等,这些取数的方法与NumPy取数方法相同,括号中索引以逗号分隔,逗号前为行,后为列。除了DataFrame自身所带有的取数方法,我们还补充了常见的两个取数方法,.loc()按照标签取行值,.iloc()通过位置取行值,使用起来更为方便。
import pandas as pd
from pandas import Series,DataFrame
import numpy as np
df_dict = {
'name':['James','Curry','Alice'],
'age':['18','20','19'],
'national':['US','China','US']
}
df = pd.DataFrame(data=df_dict,index=['0','1','2'])
print(df)
'''
name age national
0 James 18 US
1 Curry 20 China
2 Alice 19 US
'''
#---------------------------------------
# 获取形状 行数和列数
print(df.shape)
# 获取行索引,列表显示
print(df.index.tolist())
# 获取列索引 列表显示
print(df.columns.tolist())
# 获取数据的类型
print(df.dtypes)
# 获取数据的维度
print(df.ndim)
# values属性 不以行列的形式,直接查看所有的值 会以二维ndarray的形式返回DataFrame的数据
print(df.values)
# 展示df的概览 常用方法,了解数据的全貌
print(df.info())
# 显示头几行,默认显示5行 如果数据量非常大,可以通过观察前几行和末尾行的数据来了解数据的完整性和情况。
print(df.head(2))
# 显示后几行
print(df.tail(1))
'''
(3, 3)
['0', '1', '2']
['name', 'age', 'national']
name object
age object
national object
dtype: object object是字符串
2
[['James' '18' 'US']
['Curry' '20' 'China']
['Alice' '19' 'US']]
<class 'pandas.core.frame.DataFrame'>
Index: 3 entries, 0 to 2
Data columns (total 3 columns):
name 3 non-null object
age 3 non-null object
national 3 non-null object
dtypes: object(3)
memory usage: 96.0+ bytes
None
解读:df.info()显示索引,列,列名 一列多少数据(行), non-null 数据非空,类型是object字符串,占用内存
None是无返回值,这里的和jupyter编辑器中使用的print函数有关,帮助显示df.info()有无返回值,了解即可
name age national
0 James 18 US
1 Curry 20 China
name age national
2 Alice 19 US
'''
#----------------------------------
'''
df.loc 通过标签索引行数据
标签一般都是以字符串数据来保存
'''
# 获取某一行某一列的
print(df.loc['0','name'])
# 一行所有列
print(df.loc['0',:])
# 某一行多列的数据
print(df.loc['0',['name','age']])
# 选择间隔的多行多列
print(df.loc[['0','2'],['name','national']])
# 选择连续的多行和间隔的多列
print(df.loc['0':'2',['name','national']])
'''
James
name James
age 18
national US
Name: 0, dtype: object
name James
age 18
Name: 0, dtype: object
name national
0 James US
2 Alice US
name national
0 James US
1 Curry China
2 Alice US
'''
#---------------------
'''
df.iloc 通过位置获取行数据
位置代表索引,以数值型数据保存
'''
# 取一行
print(df.iloc[1])
# 取连续多行
print(df.iloc[0:2])
# 取间断的多行
print(df.iloc[[0,2],:])
# 取某一列
print(df.iloc[:,1])
# 某一个值
print(df.iloc[1,0])
# 修改值
df.iloc[0,0]='panda'
print(df)
# dataframe中的排序方法
df = df.sort_values(by='age',ascending=False) # ascending=False : 降序排列,默认是升序
print(df)
'''
name Curry
age 20
national China
Name: 1, dtype: object
name age national
0 James 18 US
1 Curry 20 China
name age national
0 James 18 US
2 Alice 19 US
0 18
1 20
2 19下·
Name: age, dtype: object
Curry
name age national
0 panda 18 US
1 Curry 20 China
2 Alice 19 US
name age national
1 Curry 20 China
2 Alice 19 US
0 panda 18 US
'''
DataFrame修改index、columns
import pandas as pd
from pandas import Series,DataFrame
import numpy as np
df1 = pd.DataFrame(np.arange(9).reshape(3, 3), index = ['bj', 'sh', 'gz'], columns=['a', 'b', 'c'])
print(df1)
'''
b c
bj 0 1 2
sh 3 4 5
gz 6 7 8
Index(['bj', 'sh', 'gz'], dtype='object')
'''
# 修改 df 的 index
print(df1.index) # 可以打印出print的值,同时也可以为其赋值
df1.index = ['beijing', 'shanghai', 'guangzhou']
print(df1)
# 使用rename函数,给行索引和列名加上‘_ABC’ 通过自定义函数(x是原有的行列值) 实现
def test_map(x):
return x+'_ABC'
# inplace:布尔值,默认为False。指定是否返回新的DataFrame。如果为True,则在原df上修改,返回值为None。
print(df1.rename(test_map, columns=test_map, inplace=True))
print(df1)
# 如果是inplace设置为False,不在原df上修改,则会产生一个新的数组,可以新建一个变量来接收;
# 写法是 result = df.rename(index=test_map, columns=test_map) print(result))
# 同时, rename 还可以传入字典,为某个 index 单独修改名称
df2 = df1.rename(index={'beijing_ABC':'beijing'}, columns = {'a_ABC':'aa'})
print(df2)
'''
a b c
beijing 0 1 2
shanghai 3 4 5
guangzhou 6 7 8
Index(['bj', 'sh', 'gz'], dtype='object')
a b c
beijing 0 1 2
shanghai 3 4 5
guangzhou 6 7 8
None
a_ABC b_ABC c_ABC
beijing_ABC 0 1 2
shanghai_ABC 3 4 5
guangzhou_ABC 6 7 8
aa b_ABC c_ABC
beijing 0 1 2
shanghai_ABC 3 4 5
guangzhou_ABC 6 7 8
'''
# --------------------
# 列转化为索引
df3=pd.DataFrame({'X':range(5),'Y':range(5),'S':list("abcde"),'Z':[1,1,2,2,2]})
print(df3)
'''
X Y S Z
0 0 0 a 1
1 1 1 b 1
2 2 2 c 2
3 3 3 d 2
4 4 4 e 2
'''
# 将一列数据改变为行索引 (drop=False 指定列作为索引列的同时保留指定列的数据不删除,默认是不保留)
result = df3.set_index('S',drop=False)
result.index.name=None # 将索引列的标签名去除,可以将这行注释观察结果,行索引列上有一个‘S’,指定为None后可以消除
print(result)
'''
X Y S Z
a 0 0 a 1
b 1 1 b 1
c 2 2 c 2
d 3 3 d 2
e 4 4 e 2
将一列数据变为行索引的好处是,索引从0开始,如果要按照表格中的一列,如id列中的序号,从1开始,可以将其指定为行索引顺序
'''
# 拓展: reset_index()把索引变成某一列 可以自己尝试,就不演示了
添加数据
import pandas as pd
from pandas import Series,DataFrame
import numpy as np
df1 = pd.DataFrame([['Snow','M',22],['Tyrion','M',32],['Sansa','F',18],['Arya','F',14]],columns=['name','gender','age'])
# 在数据框最后加上score一列
df1['score']=[80,98,67,90] # 增加列的元素个数要跟原数据的行数一样
print(df1)
'''
name gender age score
0 Snow M 22 80
1 Tyrion M 32 98
2 Sansa F 18 67
3 Arya F 14 90
'''
# 在具体某个位置插入一列可以用insert的方法
# 语法格式:列表.insert(index, obj) index: obj 需要插入的索引位置(行)。obj 要插入列表中的对象(列名)
col_name=df1.columns.tolist() # 将数据框的列名全部提取出来存放在列表里
col_name.insert(2,'city') # 在列索引为2的位置插入一列,列名为:city;插入一列,没有值,整列都是NaN
df1=df1.reindex(columns=col_name) # DataFrame.reindex() 对原行/列索引重新构建索引值;将新的列名加进去
print(df1)
df1['city']=['北京','山西','湖北','澳门']
print(df1)
'''
name gender city age score
0 Snow M NaN 22 80
1 Tyrion M NaN 32 98
2 Sansa F NaN 18 67
3 Arya F NaN 14 90
name gender city age score
0 Snow M 北京 22 80
1 Tyrion M 山西 32 98
2 Sansa F 湖北 18 67
3 Arya F 澳门 14 90
'''
# 方法二:df中的insert,插入一列
df2 = pd.DataFrame([['Snow','M',22],['Tyrion','M',32],['Sansa','F',18],['Arya','F',14]],columns=['name','gender','age'])
print(df2)
# df.insert(iloc,column,value) iloc:要插入的位置 colunm:列名 value:值
df2.insert(2,'score',[80,98,67,90])
print(df2)
'''
name gender age
0 Snow M 22
1 Tyrion M 32
2 Sansa F 18
3 Arya F 14
name gender score age
0 Snow M 80 22
1 Tyrion M 98 32
2 Sansa F 67 18
3 Arya F 90 14
'''
# 插入一行
df3 = pd.DataFrame([['Snow','M',22],['Tyrion','M',32],['Sansa','F',18],['Arya','F',14]],columns=['name','gender','age'])
row=['111','222','333']
df3.iloc[1]=row
print(df3)
'''
name gender age
0 Snow M 22
1 111 222 333
2 Sansa F 18
3 Arya F 14
'''
# 增加数据 append方法
df = pd.DataFrame([['Snow','M',22],['Tyrion','M',32],['Sansa','F',18],['Arya','F',14]],columns=['name','gender','age'])
# 先创建一个DataFrame,用来增加进数据框的最后一行
new=pd.DataFrame({'name':'lisa','gender':'F','age':19 },index=[0])
print(new)
# print("--在原数据框df最后一行新增一行,用append方法")
df4=df.append(new,ignore_index=True) # ignore_index=False,表示不按原来的索引,从0开始自动递增
print(df4)
'''
name gender age
0 lisa F 19
name gender age
0 Snow M 22
1 Tyrion M 32
2 Sansa F 18
3 Arya F 14
4 lisa F 19
'''
数据的合并、删除
数据的合并、删除方法和NumPy中的数组方法类似。
import pandas as pd
from pandas import Series,DataFrame
import numpy as np
# 合并
df1 = pd.DataFrame(np.arange(6).reshape(3,2),columns=['four','five'])
df2 = pd.DataFrame(np.arange(6).reshape(2,3),columns=['one','two','three'])
display(df1,df2)
'''
four five
00 1
12 3
24 5
one two three
00 1 2
13 4 5
----------------------------------
拼接 concat(objs,axis,ignore_index)
objs:合并对象
axis:合并方式,默认0表示按列合并,1表示按行合并
ignore_index:是否忽略索引
'''
# 按行合并
result = pd.concat([df1,df2],axis=1)
print(result)
'''
four five one two three
0 0 1 0.0 1.0 2.0
1 2 3 3.0 4.0 5.0
2 4 5 NaN NaN NaN
'''
# 按列合并
result = pd.concat([df1,df2],axis=0,ignore_index=True)
print(result)
'''
five four one three two
0 1.0 0.0 NaN NaN NaN
1 3.0 2.0 NaN NaN NaN
2 5.0 4.0 NaN NaN NaN
3 NaN NaN 0.0 2.0 1.0
4 NaN NaN 3.0 5.0 4.0
'''
# DataFrame的删除
'''
drop(lables,axis,inplace)
lables:要删除数据的标签
axis:0表示删除行,1表示删除列,默认0
inplace:是否在当前df中执行此操作
'''
df3 = pd.DataFrame(np.arange(9).reshape(3,3),columns=['one','two','three'])
print(df3)
df4 = df3.drop([0,1],axis=0, inplace=True) # 删除第一,第二行
# # df5=df3.drop(['three'],axis=1, inplace=True)) # 删除第一列
print(df3)
'''
one two three
0 0 1 2
1 3 4 5
2 6 7 8
one two three
2 6 7 8
'''
数据处理
这一部分是比较重要的,含有数据预处理中的一些概念。NumPy比起Pandas方便的原因也是它提供很多的函数可以对数据进行处理。数据的处理包含以下四个部分:
对Series过滤NaN
对DataFrame过滤NaN
填充缺失数据
移除重复数据
from numpy import nan as NaN
# 通过pandas中的dropna()直接滤除缺失数据:
#-----------------------------------
# 1.处理Series对象
se=pd.Series([4,NaN,8,NaN,5])
print(se)
se1 = se
print(se1.dropna())
se2 = se
print(se2.notnull())
se3=se
print(se3.isnull())
'''
0 4.0
1 NaN
2 8.0
3 NaN
4 5.0
dtype: float64
0 4.0
2 8.0
4 5.0
dtype: float64 # dropna()去除Nan
0 True
1 False
2 True
3 False
4 True
dtype: bool # notnull())
0 False
1 True
2 False
3 True
4 False
dtype: bool # isnull())
'''
# # 通过布尔序列也能滤除:
se4 = se
print(se4[se4.notnull()]) # se4[取bool=True的行]
'''
0 4.0
2 8.0
4 5.0
dtype: float64
'''
#--------------------------------------------
# 2 处理DataFrame对象
from numpy import nan as NaN
import pandas as pd
df=pd.DataFrame([[1,2,3],[NaN,NaN,2],[NaN,NaN,NaN],[8,8,NaN]])
print(df)
'''
0 1 2
0 1.0 2.0 3.0
1 NaN NaN 2.0
2 NaN NaN NaN
3 8.0 8.0 NaN
'''
# 滤除所有包含NaN的行:
df1 = df
print(df1.dropna())
'''
0 1 2
0 1.0 2.0 3.0
'''
# 传入how=‘all’滤除全为NaN的行:
df2 = df
print(df2.dropna(how='all')) # 默认情况下是how='any',只要有nan就删除
'''
0 1 2
0 1.0 2.0 3.0
1 NaN NaN 2.0
3 8.0 8.0 NaN
'''
# 传入axis=1滤除列:
df3 = df
print(df3.dropna(axis=1,how="all"))
'''
0 1 2
0 1.0 2.0 3.0
1 NaN NaN 2.0
2 NaN NaN NaN
3 8.0 8.0 NaN
没有变化,因为没有一列全是NaN
'''
#传入thresh=n保留至少有n个非NaN数据的行:
df4 = df
print(df4.dropna(thresh=1)) # thresh等于1表示一行含有一个非NaN的数据则保留
df5 = df
print(df5.dropna(thresh=2)) #如果thresh等于2则表示一行含有两个以上非NaN会被保留
'''
0 1 2
0 1.0 2.0 3.0
1 NaN NaN 2.0
3 8.0 8.0 NaN
0 1 2
0 1.0 2.0 3.0
3 8.0 8.0 NaN
'''
#--------------------------------
#3.填充缺失数据
df6 = df
print(df6)
'''
0 1 2
0 1.0 2.0 3.0
1 NaN NaN 2.0
2 NaN NaN NaN
3 8.0 8.0 NaN
'''
# 用常数(0)填充fillna
df7 = df
print(df7.fillna(0))
'''
0 1 2
0 1.0 2.0 3.0
1 0.0 0.0 2.0
2 0.0 0.0 0.0
3 8.0 8.0 0.0
'''
# 通过字典填充不同的常数
print(df7.fillna({0:10,1:20,2:30})) # 第一、二、三列中的NaN填充为10,20,30
'''
0 1 2
0 1.0 2.0 3.0
1 10.0 20.0 2.0
2 10.0 20.0 30.0
3 8.0 8.0 30.0
'''
#---------------------------------
#4.移除重复数据
''' DataFrame中经常会出现重复行,利用duplicated()函数返回每一行判断是否重复的结果(重复则为True) '''
df=pd.DataFrame({'A':[1,1,1,2,2,3,1],'B':list("aabbbca")})
print(df)
'''
A B
0 1 a
1 1 a
2 1 b
3 2 b
4 2 b
5 3 c
6 1 a
'''
# 判断每一行是否重复(结果是bool值,TRUE代表重复的)
df9 = df
print(df9.duplicated())
'''
0 False
1 True
2 False
3 False
4 True
5 False
6 True
dtype: bool
'''
# 去除全部的重复行
print(df9.drop_duplicates())
'''
A B
0 1 a
2 1 b
3 2 b
5 3 c
'''
# 指定列去除重复行
df10 = df
print(df10.drop_duplicates(['A']))
'''
A B
0 1 a
3 2 b
5 3 c
# 可以试试指定列B,观察不同
'''
# 保留重复行中的最后一行
df11 = df
print(df11.drop_duplicates(['A'],keep='last'))
'''
A B
4 2 b
5 3 c
6 1 a
'''
# 去除重复的同时改变DataFrame对象
df12 = df
df12.drop_duplicates(['A','B'],inplace=True)
print(df12)
'''
A B
0 1 a
2 1 b
3 2 b
5 3 c
'''
小作业
尝试用pandas进行数据查询
在公众号后台回复“查询”会有一份csv文件
请查询改数据集指定的行与列
写在后面:
今天的数据挖掘初探-商品推荐是不是很有意思的~
跟随我们的脚步,继续学习~
记得打卡,在群里分享你的代码和笔记~
好文章,我在看❤