1/关于pypi
python本身的数据分析能力并不是很强,需要安装一些第三方库来增强它的能力,丰富它的武器库
python的第三方库有numpy,pandas,matplotlib,scipy,keras,sklearn,gensim等
如果你安装的是anaconda发行版,那么它已经自带了numpy,pandas,scipy等第三方库
我们可以自行安装一些第三方库,这样可以做一切我们想做的事情。
pypi是第三方库的仓库,我们可以把第三方库统称为pypi。
复制代码
2/numpy
python本身并没有提供数组功能,虽然列表可以完成基本的数组功能,但是列表不是真正的数组.
而且在数据量大的情况下,使用列表的速度会慢的让人难以接受。
因此第三方库numpy提供了真正的数组功能,以及对数组进行快速处理的函数。
numpy内置函数处理数据的速度是c语言级别的。
import numpy as np
arr1 = np.array( [11,22,33] ) # 创建一维数组
arr2 = np.array( [ [11,22,33],[44,55,66] ] ) # 创建二维数组2行3列
print(arr2 * arr2) # 这是数组相乘,对应位置的元素相乘
numpy 提供了多维数组功能,但是它只是一般的数组,并不是矩阵。
例如当2个数组相乘时,只是对应元素相乘,而不是矩阵乘法.
复制代码
3/scipy
scipy提供了真正的矩阵,以及大量基于矩阵运算的对象和函数
scipy是一种使用numpy来做最优化,线性代数,积分,插值,拟合,快速傅立叶变换,高等数学、信号处理、优化、统计和许多其它科学任务的语言扩展。
复制代码
4/matplotlib
matplotlib 是用来做可视化的python第三方库,主要用于二维绘图,也可以用于简单的三维绘图
用matplotlib第三方库绘图时,有3个常用概念,
figure:一个是执行程序时弹出的窗口,叫做figure,figure相当于一个大的画布。
axes: 在每个figure中,又可以存在多个子图(当然也可以只有一个子图),这种子图叫做axes
axis: 在每个子图axes中,都有坐标轴,即axis
复制代码
在图形中添加水平线/垂直线
plt.axhline(y=4,ls=":",c="yellow") # 在y=4的地方添加水平直线
plt.axvline(x=4,ls="-",c="green") # x=4的地方添加垂直直线
复制代码
显示字体
import matplotlib.pyplot as plt
plt.rcParams["font.family"] = ["Arial Unicode MS"] # 规定字体
plt.rcParams["font.sans-serif"] = ["SimHei"] # 用黑体显示中文
plt.rcParams['font.sans-serif'] = ["Microsoft JhengHei"] # 显示中文 YaHei JhengHei
plt.rcParams['axes.unicode_minus'] = False # 正常显示负号
复制代码
常用命令
import matplotlib.pyplot as plt
fig = plt.figure(num='fig的名字',figsize=(a,b))
# 创建一块画布fig,命名整体图的标题(是num='',而不是title=''),
# figsize=(长,宽)规定画布的大小
# 在fig中绘制第一张子图:曲线图
axes1 = fig.add_subplot(311)
在画布fig中添加子图,311的意思是:3行1列中的第一个
即使画布中只有一个子图,也要设置为:fig.add_subplot(111)
axes1.set_title("xxxxx") # 定义子图标题
axes1.set_xlim([]) # 设置x轴的范围
axes1.set_ylim([]) # 设置y轴的范围
axes1.set_xticklabels() # 设置x轴标签
axes1.set_yticklabels() # 设置y轴标签
axes1.set_xticks() # 设置x轴上每个标签的具体位置
axes1.set_yticks() # 设置x轴上每个标签的具体位置
axes1.set_xlabel() # 设置x轴标签
axes1.set_ylabel() # 设置y轴标签
axes1.plot() # 绘制线图
# 在fig中绘制第二张子图:饼图
axes2 = fig.add_subplot(312) # 定义第二个子图(3行1列中的第二个)
axes2.pie(sizes, explode=explode, labels=labels, colors = colors, autopct='%1.1f%%', shadow=True, startangle=45) #绘制饼图,饼状图中需要包括每一部分的大小/每一部分的标签/每一部分的颜色,autopct的作用是自动以百分数的形式展现,保留一位小数,shadow是有阴影,startagle是指从什么角度开始(逆时针)
axes2.axis(“equal”) # 保证饼图不变形,是标准的圆
axes2.pie() # 绘制饼状图
# 在fig中绘制第三张子图:堆叠图
axes3 = fig.add_subplot(313)
axes3.bar(x, y1, color='r', label='语文')
axes3.bar(x, y2, bottom=y1, color='g', label='数学')
axes3.bar(x, y3, bottom=y1+y2, color='c', label='英语')
axes3.set_xlim(1,20) # 显示范围
axes3.set_ylim(1,100) # 显示范围
# 添加图例
axes3.legend(loc='upper right') # 绘制图例
axes3.grid(axis='y', color='gray', linestyle='-.', linewidth=1) # 绘制网格线,只在y轴中绘制,颜色,线条类型,线条宽度
plt.grid() # 绘制网格线
plt.show() # 不管fig中有几个子图,各个子图绘制完成后,如果最后想展示出来,都要掉用plt.shot()函数
plt.savefig(path,dpi=1000,format="pdf") # 保存fig,dpi是分辨率,format是存储形式
matplotlib.use("Agg") # 绘制的画布只保存,不显示,前提是要把plt.show()给注释掉
复制代码
5/pandas
pandas的基本的数据结构是series和dataframe。
series是一维数组,dataframe是二维数组。
dataframe中的一列的数据类型必须是相同的,不同列之间的数据类型可以是不同的
复制代码
pandas显示问题
# 显示所有行,这样不会因为行数太多而省略中间的行数据
pd.set_option("display.max_rows",None)
# 显示所有列,列数据不会被省略,但是可能会因为行最大显示字符长度的原因,导致自动换行
pd.set_option("display.max_columns",None)
# 单个value最大显示字符数,默认为50
pd.set_option("max_colwidth",500)
# 一行最大显示字符数,禁止自动换行
pd.set_option("display.width",10000)
复制代码
value的替换
dataframe = dataframe.replace({"xxx":["None","none"]},"2099-12-31")
# 把"xxx"这一列中的"None"和"none"替换为"2019-12-31"
dataframe[column] = dataframe[column].replace(a,b)
# 把dataframe的某一列中的a替换为b
dataframe = dataframe.replace(a,b)
# 把整个dataframe中所有的a替换为b
dtaframe = dataframe.replace([a,aa,aaa],bbb)
# 把整个dataframe中的a,aa,aaa都替换为bbb
dataframe["列名"] = dataframe["列名"].replace([a,aa,aaa],bbb)
# 把指定列中的a,aa,aaa都替换为bbb
复制代码
判断dataframe为空
方法有3
<1>直接用len(df),如果为0,则该df为空的df,否则不为空,len(df)得到的是该df的行数
<2>DataFrame有一个属性为empty,直接用DataFrame.empty判断就行。
如果df为空,则 df.empty 返回 True,反之 返回False。
注意empty后面不要加()。
<3>dataframe.shape() 返回形状,即几行几列的dataframe.
shape[0]=rows,shape[1]=columns
复制代码
创建空dataframe
方法有3:
empty_df = pd.DataFrame(data=None,columns=range(1,5),index=[0,1])
# 有数据(但是数据为空),有列名,有索引
empty_df = pd.DataFrame(data=None)
# 有数据(但是数据为空),没有列名,没有索引
empty_df = pd.DataFrame(columns=["a","b","c"])
# 只有列名,没有索引
复制代码
dataframe.loc[]和dataframe.iloc[]的区别
dataframe.loc[]是基于行标签和列标签(x_label、y_label)进行查找
dataframe.iloc[]是基于行索引和列索引(index,columns)进行查找,都是从0开始,
如果数据的行标签和列标签名字太长或不容易记,则用 .iloc[] 很方便,只需记标签对应的索引即可。
复制代码
创建dataframe的2种方式
<1>用字典的方式,一个kv就是一列数据
dict1 = {'name':['ccc', 'aaa', 'bbb'], 'age':[20,21,23]}
data_df = pd.DataFrame(dict1,index=xxx)
# dict1中的一个key:value是一列,key就是列名
<2>用列表的的形式,一个列表就是一行数据,
data_df = pd.DataFrame( [[],[],[]....],columns=[],index=[])
list1 = [ [1,2,3], [4,5,6], [7,8,9] ]
data_df = pd.DataFrame(list1,index=xxx,columns=xxx)
如果index没有,默认就是递增的数字
复制代码
dataframe按照某一列进行排序
new_df = old_df.sort_values(by="列名",ascending=True)
by指定列名, ascending默认为升序(即ascending=True),当ascending=False时,则为降序排列
11/读取df数据文件时,可以选择性读取字段,无需所有字段都读取
data_df = pd.read_csv(filepath, encoding="gb18030", usecols=["xxx","xxx"])
# usecols一定要在encoding之后写
复制代码
在dataframe中添加行数据 && 添加列数据
df = df.append(dic,ignore_index=True)
# ignore_index = True 就是是自动按照已有的index顺序添加行,
dic是一个字典{列名1:value,列名2:value,列名3:value}
df[新列名] = []
df.insert(loc=0,column="列名",value="xxx")
复制代码
保存dataframe对象
data_df.to_csv(path,index=False,encoding="gb18030")
# index=False就是把dataframe中的index列去掉
复制代码
在dataframe中,把字符串转换为时间格式?
data_df["出生日期"] = pd.to_datetime(data_df["出生日期"])
# 把字符串转换为时间,如果出生日期是空值或者格式错误,会显示为NaT
data_df["离职日期"] = pd.to_datetime(data_df["离职日期"].fillna("2099-12-31"))
复制代码
dataframe去重
df.drop_duplicates(subset=['a','b'],keep='first',inplace=False)
# subset="列名" 如果是多列subset=['列名1','列名2']
参数解读:
subset :用来指定特定的列,默认所有列。
keep : {‘first’, ‘last’, False}, default ‘first’。
保留第一个,保留最后一个,全部删除
inplace: inplace=True表示直接在原来的DataFrame上删除重复项,而默认值False表示生成一个新的dataframe对象。
df.drop_duplicates(subset='id',keep='first',inplace=True)
#不用在赋值给一个变量
df = df.drop_duplicates(subset='id',keep='first',inplace=False)
# inplace可以省略,因为默认为False
复制代码
dataframe.insert()函数
pandas.get_dummies()
有一个变量x,假如x变量是一个分类变量,比如血型,有a,b,ab,o。
则经过get_dummies()之后,会编程4个变量,x_a,x_b,x_ab,x_o,
其值用0和1表示。
这就是one_hot,独热编码。
复制代码
get_dummies(数据列) 可选参数(prefix=加前缀 其他的参数没用过)
复制代码
根据Embarked列的三个唯一取值,转换为三个虚拟变量,并且利用prefix对名字做了前缀添加
复制代码
dataframe.sample()
有时候我们只需要数据集中的一部分数据,并不需要全部的数据。
这个时候我们就要对数据集进行随机的抽样。
pandas中自带有抽样的方法。
应用场景:
我有10W行数据,每一行都11列的属性。
现在,我们只需要随机抽取其中的2W行。
实现方法很简单:
利用Pandas库中的sample方法
DataFrame.sample(n=None,
frac=None,
replace=False,
weights=None,
random_state=None,
axis=None)
参数解释:
n是要抽取的行数(例如n=20000时,抽取其中的2W行)
frac是抽取的比列(有一些时候,我们对具体抽取的行数并不关心,我们想抽取其中的百分比,这个时候就可以选择使用
frac,例如frac=0.8,就是抽取其中80%)
replace:是否为有放回抽样,取replace=True时为有放回抽样。
weights这个是每个样本的权重,具体可以看官方文档说明。
random_state这个在之前的文章已经介绍过了。
axis是选择抽取数据的行还是列。axis=0的时是抽取行,axis=1时是抽取列(也就是说axis=1时,在列中随机抽取n列,在axis=0时,在行中随机抽取n行)
复制代码
对dataframe进行洗牌
from sklearn.utils import shuffle
new_df = shuffle(df)
复制代码
在dataframe中,改变某列或者某几列的数据类型
df = df.astype({列名1:新数据类型,列名2:新数据类型}) # 以字典的形式
df['列名'] = df["列名"].astype(np.float64) # 对某一列及进行数据类型的修改
df["xxx"] = base_df["xxx"].apply(int) # 把xxx列转化为int
复制代码
在dataframe中对某一列数据保留3位小数?
format = lambda x : "%.3f" % x
df[列名] = df[列名].map(format) # 保留3位小数
复制代码
fillna()的应用
fillna_values = {'列名1': 1, '列名2': 2, '列名3': 3} # 首先定义好在每一列都fillna什么值
df = df.fillna(value=fillna_values)
# 对列名1中的空值填充1,对列名2中的空值填充2,对列名3中的空值填充3
df = df.fillna(value=fillna_values, limit=1)
# 只填充第一个空值,剩下的空值不进行填充
fillna_value = {'price':df["price"].mean()}
# 计算出df中price列的均值
df = df.fillna(value=fillna_value)
# 然后把这个均值补充在df中姓名这一列的空值中
复制代码
如何对dataframe进行深度复制?
df2 = df1.copy(deep=True)
深度复制:相当于在内存中存储了2个完全不相关的对象,df1对象发生改变,df2对象不会跟着改变。
如果不是深度拷贝,相当于在一个对象上有2个变量名,只要对象发生改变,在引用的时候,2个变量都会发生变化
复制代码
df中如何筛选数据?
注意: 有isin(),没有notin()
注意: 有isnull(),也有notnull()
temp_df = temp_df[ (temp_df["离职日期"] >= date) & (temp_df['职级'].isin(['K3A','K3B','K3C','K4A','K4B','K4C'])) & ( temp_df['面评'].notnull() ) & ( temp_df['绩效'].notnull() ) ].reset_index(drop=True) # 面评和绩效都不为空
temp_df = temp_df[ (temp_df["离职日期"] >= date) & (temp_df['职级'].isin(['K3A','K3B','K3C','K4A','K4B','K4C'])) & ( temp_df['面评'].isnull() ) & ( temp_df['绩效'].isnull() ) ].reset_index(drop=True) # 面评和绩效都为空。
复制代码
在dataframe中,删除行和列
data_df = data_df.drop(columns=列名) # 是columns,而不是column,如果是想删除多列,就[ ]
data_df = data_df.drop(index=行号) # 如果是想删除多行,就用[]扩起来
data_df = data_df.dropna() # 任何一个字段有空值,就删除整行数据
复制代码
dataframe按照行遍历的几种方式?
<1>df.iterrows(): 按行遍历,将DataFrame的每一行迭代为(index, Series)对,可以通过row[name]对元素进行访问。
for index, row in df.iterrows():
print(index) # 输出每行的索引值
for row in df.iterrows():
print(row['c1'], row['c2']) # 输出每一行中指定字段的value
<2>df.itertuples(): 按行遍历,将DataFrame的每一行迭代为元祖,可以通过row[name]对元素进行访问,比iterrows()效率高。
for row in df.itertuples(): # 效率比iterrows()好
print(getattr(row, 'c1'), getattr(row, 'c2')) # 输出每一行
<3>df.iteritems():按列遍历,将DataFrame的每一列迭代为(列名, Series)对,可以通过row[index]对元素进行访问。
for index, row in df.iteritems():
print(index) # 输出列名
for row in df.iteritems():
print(row[0], row[1], row[2]) # 输出各列
复制代码
dataframe修改列名
2种方式:
final_data_df.rename(columns={'A':'a', 'B':'b'},inplace=True) # 任意修改列名
final_data_df.columns = ["","","",""] # 这种方式,如果想修改一个列名,必须把所有列都写上
复制代码
筛选value值为具体长度的数据
new_data_df = data_df[ data_df['xxx'].str.len() == 6 ]
new_data_df = data_df[ data_df['content'].str[:10] == '2019-11-12' ]
复制代码
None和np.nan
<1> None是python自带的,其类型是python object。
因此None不能参与到任何计算中。
object类型的运算要比int型慢很多
<2> np.nan是浮点类型,能参与到计算中。但计算的结果总是NaN。
<3> 数据库中的NULL对应的是python中的None
复制代码
自定义dataframe时如何为个别元素赋空值和缺失值
字符串类型的,使用None赋值为空值
数值类型的,使用numpy.NaN赋值为空值
时间类型的,使用pandas.NaT赋值为空值
例子:
testframe = pd.DataFrame({'c1':[None, 'b'],
'c2':[1, np.NaN],
'c3':[pd.Timestamp('2018-09-23'), pd.NaT]})
c1 c2 c3
0 None 1.0 2018-09-23
1 b NaN naT
复制代码
dataframe中between_time()函数的用法
dataframe["9-10"] = dataframe["a"].between(-52,11)
# 两边都是闭区间,返回值是True和False
复制代码
dataframe筛选出含有某个字符的数据?
df = df[ df["xxx"].str.contains("word") ] # 列xxx的value中包含word
df = df[ df["xxx"].str.contains("hello|world") ] # 列xxx的value包含helle或者world
df = df[ ~df["xxx"].str.contains("word") ] # 列xxx的value中不包含word
df = df[ ~(df["xxx"].str.contains(“Hello”) | (df[xxx].str.contains(“World”)) ]
# 包含word韩式不包含hello
复制代码
整个df文件保留n位小数
dataframe = dataframe.round(2)
复制代码
dataframe中应用apply()函数和applymap()函数
<1>对dataframe中的某些行或者列处理,或者对dataframe中的每一个元素进行某种运算或操作,我们无需再利用低效笨拙的循环.
<2>datafrmae提供了直接简单的函数,apply()和applymap()。
<3>其中apply()函数是针对某些行或列进行操作的,而applymap()函数则是针对所有元素进行操作的。
<4>apply()对行和列进行处理
df['wide petal'] = df['petal width'].apply(lambda v: 1 if v >= 1.3 else 0)
df['petal area'] = df.apply(lambda r: r['petal length'] * r['petal width'], axis=1)
<5>applymap()对每一个value进行处理
df = df.applymap(lambda v: np.log(v) if isinstance(v, float) else v)
复制代码
dataframe填充
<1> 整个dataframe填充
df = df.fillna(method="ffill") # 向下填充,即下面的数据和上面的一样
df = df.fillna(method="bfill") # 向上填充,即上面的数据和下面的一样
<2> 对某个字段进行填充
df["col_name"] = df["col_name"].fillna(method="ffill")
# 向下填充,即下面的数据和上面的一样
df["col_name"] = df["col_name"].fillna(method="bfill")
# 向上填充,即上面的数据和下面的一样
复制代码
对dataframe数据结构的某一列数据求和
data_df["xxx"].sum()
# xxx为需要求和的列名,前提是xxx这一列必须是数值型的字段
复制代码
dataframe删除含有空值的行
df.dropna(axis=0,how="any",inplace=True)
axis:
0: 行操作(默认)
1: 列操作
how:
any: 只要有空值就删除(默认)
all:全部为空值才删除
inplace:
False: 返回新的数据集(默认)
True: 在原数据集上操作,也就是说直接替换了原来的df
复制代码
计算一个列表的分位值
import numpy as np
a =[1,2,3,4,5,6,7,8,9,10]
print(np.median(a)) # 中位数
print(np.percentile(a,25)) # 25%分位数
print(np.percentile(a,75)) # 75%分位数
不管a中的顺序是什么样的,在计算分位值的时候,都会默认对a进行从小到大的排序,我们不需要管
复制代码
np.unique(list,return_counts=True)
该函数是对可迭代序列进行去重处理,参数return_counts如果为True,则返回每个元素重复的次数
事例
values,cnts = np.unique(list,return_counts=True)
# 去重,并且返回重复的次数。返回2个列表对象,第一个是去重后的列表,第二个是重复次
second_level_nodes_list = ([k for k,v in dict(zip(value,cnts)).items() if v >= 50])
复制代码
dataframe转换为dict
output_df = input_df.to_dict(orient="records")
output_df = input_df.to_json(orient="records")
原始数据如下:
input_df =
复制代码
output_df = input_df.to_dict(orient="xxx") # orient: 汉语意思是朝向
# 参数orient可以是['dict', 'list', 'series', 'split', 'records', 'index']中的任意一种来决定字典中值的类型
<1> output_df = input_df.to_dict(orient="records")
[{'工号':'7067769','性别':'男','婚姻状况':'未婚','员工性质':'正式员工','员工类型':'一线','年龄':28.4,'司龄':53.6},
{'工号':'2834031','性别':'女','婚姻状况':'已婚','员工性质':'正式员工','员工类型':'一线','年龄':32.5,'司龄':48.3}]
<2> output_df = input_df.to_dict(orient="list")
{'工号': ['7067769', '2834031'],
'性别': ['男', '女'],
'婚姻状况': ['未婚', '已婚'],
'员工性质': ['正式员工', '正式员工'],
'员工类型': ['普通', '普通'],
'年龄': [47.5, 55.8],
'司龄': [31.7, 51.1]}
<3> output_df = input_df.to_dict(orient="index")
{0: {'工号':'7067769','性别':'男','婚姻状况':'未婚','员工性质':'正式员工','员工类型':'销售','年龄':41.2,'司龄':43.5},
1: {'工号':'2834031','性别':'女','婚姻状况':'已婚','员工性质':'正式员工','员工类型':'一线','年龄':26.2,'司龄':43.9}}
复制代码
6/sklearn
机器学习相关的库,提供了强大的机器学习工具箱,包括数据预处理,分类,回归,聚类,预测,模型分析等。
sklearn 作为机器学习的库虽然很强大,但是它不包括一种强大的模型,即神经网络。
正好keras弥补了这一缺点。
复制代码
7/keras
keras是除了TensorFlow之外,用的最多的深度学习框架
keras是用来做深度学习的。tensorflow比较难学,keras是高度封装好的,适合新手学习。
复制代码
8/gensim
gensim:用来处理语言方面的任务,例如文本相似度 word2vec等。
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END