目录
python 数据分析学习路径
从数据采集、清洗、处理、分析、报表、数据挖掘、机器学习,Python都提供了成熟的 解决方案,可以说学会了Python,可以在数据分析领域上天入地。事实上,Python的一些常用库,比 如像数据分析三剑客(Numpy/Pandas/Matpolib)等等,是数据分析师们日常必备工具。
print("Hello world")
交互式编程并不是Python独有的,但Python的交互式界面是强大的,它还有很丰富的插件,提供 了一系列非常强大的功能。
编程基础
第一部分 核心语法
变量
变量就是可变的量,对于一些有可能会经常变化的数据,我们需要使用一个符号,这样才能计算中使 用它,就像我们在小学时学过的一元方程中的"x"一样。比如说,我们在控制台内输入:
#定义变量:不以数字开头,区分大小写
x = "world"
a = b = c = 1
变量名由字母、数字和下划线组成,也就是a-z, A-Z, 0-9和_ 变量名不能以数字开头 变量名是区分大小写的,比如a 和 A就是两个不同的变量。
# 这些都是合法的变量名
a = "hello"
MyJob = "analyst"
player1 = "姚明"
_private_name = "ss"
player1_score = 41
_ = "something"
# 下面这些都是不合法的变量名
1abc # 不能以数字开头
123
abc- # 注意这是横杠符号,不是下划线
关键字
事实上,如果你一不小心定义了一个与关键字相同的变量,代码会在运行的时候报错。比如下面这个:
True = 0
# 上面这行代码运行会输出下面的信息,提示不能给关键字赋值。
# File "<stdin>", line 1
# SyntaxError: can't assign to keyword
变量赋值
变量是可以重复使用,并且是可以修改的,由于Python的变量不需要先声明,所以变量的声明和赋值是 在同一行代码完成的。变量必须要先声明,才能使用。
# 定义name变量,赋值为"Smith"
name = "Smith"
print("Mr", name)
# 修改变量的值为"Jones"
name = "Jones"
print("Mr", name)
数据类型
基本的数据类型:数值,包括整数和浮点数;字符串;布尔值
# 这是一个整形
a = 100
# 这是一个浮点型变量
b = 3.14
#这是一个字符串
a = "Hello world"
#数值类型,非零值转换为True,零值转换为False
bool(0) --->False
bool("") --->False
bool("abc") --->True
bool(None)--->False
round(3.1415926, 2) --->3.14
int(True) --->1
运算符
算术运算符/赋值运算符
比较运算符/逻辑运算符
流程控制
条件判断
score = 59
if score < 60:
print("您的考试成绩不及格")
elif score < 90:
print("您的考试成绩合格")
else:
print("您的考试成绩优秀")
主要包括for和while循环。同时在循环内部,需要临时略过某一次/跳出整个循环,就要用到break和continue。
#for和continue 打印出10以内的所有奇数相加的式子,偶数跳过
total = 0
for i in range(10):
if i % 2 == 0:
continue
print(i, end=" + ")
total += i
print(" = %s" % total)
#break打断整个循环并跳出,下述为打印小数的整数部分
s = "238.9237834829"
for i in s:
if i == '.':
print()
break
print(i, end='')
第二部分 数据结构
字符串str
字符串是一种序列,可以迭代循环,也可以按索引/切片访问。
first:格式化运算符
---------------------------
#常用,小数点位数
print("%.2f" % 3.14)
print("%.2f" % 3.1415926)
---------------------------
#%s 最广泛占位符
report = "%d年%s公司营收增长了百分之%.2f" % (2019, "腾讯", 20.28)
report = "%d年%s公司营收增长了%.2f%%" % (2019, "腾讯", 20.28)
#format 函数:{0}表示第一个参数,{1}{2}表示第二、第三个参数
'{0}的GDP为{1:,}...虽然它的GDP只有{1:,}美元,但它的人均GDP高达18万美元'.format("摩纳哥", 7100000000)
---------------------------
second:切片函数
# 每隔两个字符截取一个
"CHINA"[::2]
# 从右往左每隔两个两个字符截取一个
"CHINA"[::-2]
元祖tuple
#跟字符串一样也有count、index函数
t = ('My', 'age', 'is', 18)
t = ('solo',) # 或者不带括号 t = 'solo',
print(" ".join(t)) # 输出结果:'My age is 18'
---------------------------
#序列强制转为元祖
tuple('abc') # ('a', 'b', 'c')
列表list
可变的元祖,区别是列表可以动态增删改
# 定义一个空列表
lst = []
lst = list()
# 定义带有初始值的列表
lst = [1, 2, 3]
lst = ["a", 1, 2, 3, "b", "c"]
lst = list(range(5))
---------------------------
#增加
lst.append('x')
---------------------------
#重要函数:insert/pop/remove/clear/extend/reverse/sort/copy
lst = ['a', 'c', 'e']
# 在第二个元素'c'前面插入一个字符串'b'
lst.insert(1, 'b')
---------------------------
#extend可以添加一组
lst=[]
lst.extend(range(5))
lst.extend([5,6,7])
---------------------------
#将整个列表反转
lst.reverse()
---------------------------
#元素重新排序,从大到小
lst.sort(reverse=True)
revenue = [('1月', 5610000), ('2月', 4850000), ('3月', 6220000)]
revenue.sort(reverse=True, key=lambda x:x[1]) #排序后为 [('3月', 6220000), ('1月', 5610000), ('2月', 4850000)]
---------------------------
#列表表达式:对于一些简单的迭代过程,书写更为简洁,配合pandas处理
sales = ( ("Peter", (78, 70, 65)), ("John", (88, 80, 85)), ("Tony", (90, 99, 95)), ("Henry", (80, 70, 55)), ("Mike", (95, 90, 95)), )
#for循环常规方法
top_sales = []
for name, quarter_amount in sales:
total_amount = sum(quarter_amount)
top_sales.append((name, total_amount))
top_sales.sort(key=lambda x:x[1], reverse=True)
#列表表达式方法
top_sales = [(sale, sum(amount))for sale, amount in sales]
top_sales.sort(key=lambda x:x[1], reverse=True)
字典dict
sales = { 'Peter': 213, 'John': 253, 'Tony': 284, 'Henry': 205, 'Mike': 280 }
for key, value in sales.items():
print(key, value)
---------------------------
#获得键所对的值
sales.get('mike', 0)
---------------------------
#遍历键
for sale in sales.keys():
print(sale)
---------------------------
#计算所有值综合
sum(sales.values())
集合set
# 定义两个集合
s1 = {1, 2, 3}
s2 = {3, 4, 5}
---------------------------
# 求交集
s1.intersection(s2) # {3}
---------------------------
# 求并集
s3 = s1.union(s2)
print(s3) # {1, 2, 3, 4, 5}
---------------------------
# 是否是子集
s1.issubset(s3) # True
---------------------------
# 是否是父集
s3.issuperset(s2) # True
numpy 科学计算库
用来存储和处理大型矩阵,比python自身的嵌套列表结构高效,支持大量的维度数组与矩阵运算,针对数组运算提供大量的数学函数库,包括数学、逻辑、形状操作、排序、选择、输入输出等。
第一部分 基本操作
数组创建
import numpy as np
l = [1,3,5,7,9] #列表
arr = np.array(l)#列表转换成Numpy数组
-----------------------------------
#内置函数创建数组
import numpy as np
arr1 = np.ones(10) # 输出为array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])
arr2 = np.zeros(10) # 输出为 array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
arr3 = np.full(shape = [2,3],fill_value=2.718)
#输出为:
# array([[2.718, 2.718, 2.718],
# [2.718, 2.718, 2.718]])
arr4 = np.arange(start = 0,stop = 20,step = 2) # 等差数列 array([ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18])
arr5 = np.linspace(start =0,stop = 9,num = 10) # 等差数列 array([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])
arr6 = np.random.randint(0,100,size = 10) # int随机数array([ 4, 8, 79, 62, 34, 35, 2, 65, 47, 18])
arr7 = np.random.randn(5) # 正态分布 array([ 0.57807872, 0.37922855, 2.37936837, -0.28688769, 0.2882854 ])
arr8 = np.random.random(size = 5) # float 随机数array([0.59646412, 0.37960586, 0.38077327, 0.76983539, 0.22689201])
查看操作
import numpy as np
arr = np.random.randint(0,100,size = (3,4,5))
#输出轴数,维度
arr.ndim #输出3
#输出尺寸形状
arr.shape #输出(3,4,5)
#数组元素的总数
arr.size # 输出 3*4*5 = 60
#数据类型
arr.dtype # 输出 dtype('int64')
第二部分 数据类型
import numpy as np
---------------------
#创建时,指定
np.array([1,2,5,8,2],dtype = 'float32')# 输出ғarray([1., 2., 5., 8., 2.], dtype=float32)
---------------------
arr = [1,3,5,7,2,9,0]
# asarray 将列表进行变换
np.asarray(arr,dtype = 'float32')
# 输出:array([1., 3., 5., 7., 2., 9., 0.], dtype=float32)
---------------------
#数据类型转换astype
arr = np.random.randint(0,10,size = 5,dtype = 'int16')
# 输出:array([6, 6, 6, 6, 3], dtype=int16)
# ֵ使用astype进行转换
arr.astype('float32')
# 输出:array([1., 4., 0., 6., 6.], dtype=float32)
pandas 数据分析库
1.筛选替换
#筛选指定条件的列:
(1)指定类型
dianping_feature[dianping_feature.select_dtypes(include=['float64', 'int64']).columns]
第一部分 数据结构
print('---------------Series-----------')
#⽤列表⽣成 Series时,Pandas 默认⾃动⽣成整数索引,也可以指定索引
# ⽆论是numpy中的NAN还是Python中的None在pandas中都以缺失数据NaN对待
s1 = pd.Series(data = l) # pandas⾃动添加索引
s2 = pd.Series(data = l,index = list('abcdefhi'),dtype='float32') # 指定⾏索引
# 传⼊字典创建,key⾏索引
s3 = pd.Series(data = {'a':99,'b':137,'c':149},name = 'Python_score')
print('----------------DataFrame---------')
#DataFrame是由多种类型的列构成的⼆维标签数据结构,类似于 Excel 、SQL 表,或 Series 对象构成的 字典
import numpy as np
import pandas as pd
# index 作为⾏索引,字典中的key作为列索引,创建了3*3的DataFrame表格⼆维数组
df1 = pd.DataFrame(data = {'Python':[99,107,122],'Math':[111,137,88],'En': [68,108,43]},index = ['张三','李四','Michael'])
df2 = pd.DataFrame(data = np.random.randint(0,151,size = (5,3)),index = ['Danial','Brandon','softpo','Ella','Cindy'],columns=['Python','Math','En'])
第二部分 数据输入与输出
主要包含csv/excel/sql三种方式。
print('------------------------csv文件----------------------')
df = pd.DataFrame(data = np.random.randint(0,50,size = [50,5]), # 薪资情况 columns=['IT','化⼯','⽣物','教师','⼠兵']
df.to_csv('./salary.csv',
sep = ';', # ⽂本分隔符,默认是逗号
header = True,# 是否保存列索引
index = True) # 是否保存⾏索引,保存⾏索引,⽂件被加载时,默认⾏索引会作为⼀列
# 加载
pd.read_csv('./salary.csv',
sep = ';',# 默认是逗号
header = [0],#指定列索引
index_col=0) # 指定⾏索引
pd.read_table('./salary.csv', # 和read_csv类似,读取限定分隔符的⽂本⽂件
sep = ';',
header = [0],#指定列索引
index_col=1) # 指定⾏索引,IT作为⾏索
print('------------------------excel文件----------------------')
pip install xlrd -i https://pypi.tuna.tsinghua.edu.cn/simple
df1 = pd.DataFrame(data = np.random.randint(0,50,size = [50,5]), columns=['IT','化⼯','⽣物','教师','⼠兵'])
df2 = pd.DataFrame(data = np.random.randint(0,50,size = [150,3]),# 计算机科⽬的考试成绩
# 保存到当前路径下,⽂件命名是:salary.xls
df1.to_excel('./salary.xls',
sheet_name = 'salary',# Excel中⼯作表的名字
header = True,# 是否保存列索引
index = False) # 是否保存⾏索引,保存⾏索引
pd.read_excel('./salary.xls',
sheet_name=0,# 读取哪⼀个Excel中⼯作表,默认第⼀个
header = 0,# 使⽤第⼀⾏数据作为列索引
names = list('ABCDE'),# 替换⾏索引
index_col=1)# 指定⾏索引,B作为⾏索引
# ⼀个Excel⽂件中保存多个⼯作表
with pd.ExcelWriter('./data.xlsx') as writer:
df1.to_excel(writer,sheet_name='salary',index = False)
df2.to_excel(writer,sheet_name='score',index = False)
print('----------------------sql----------------------------')
import pandas as pd
# SQLAlchemy是Python编程语⾔下的⼀款开源软件。提供了SQL⼯具包及对象关系映射(ORM)⼯具
from sqlalchemy import create_engine
df = pd.DataFrame(data = np.random.randint(0,50,size = [150,3]),# 计算机科⽬的考试 成绩 columns=['Python','Tensorflow','Keras'])
# 数据库连接
conn = create_engine('mysql+pymysql://root:12345678@localhost/pandas? charset=UTF8MB4') # 保存到数据库
df.to_sql('score',#数据库中表名
conn,# 数据库连接
if_exists='append',#如果表名存在,追加数据
index=False,#索引是否为列,默认为True
index_label=False, #定义索引列,例如index_label='id'
dtype={'gcj_lng': DECIMAL(precision=12, scale=7)}#字段类型)
# 从数据库中加载
pd.read_sql('select * from score limit 10', # sql查询语句
conn, # 数据库连接
index_col='Python') # 指定⾏索引名
第三部分 数据选取
主要介绍一些常用对dataframe进行自定义筛选的方法。
print('--------------Part one:获取数据-----------')
import pandas as pd
import numpy as np
df = pd.DataFrame(data = np.random.randint(0,150,size = [150,3]), columns=['Python','Tensorflow','Keras'])
df['Python'] # 获取单列,Series
df.Python # 获取单列,Series
df[['Python','Keras']] # 获取多列,DataFrame,多列需要用
df[3:15] # ⾏切⽚
print('--------------Part two:标签选择-----------')
df = pd.DataFrame(data = np.random.randint(0,150,size = [10,3]),index = list('ABCDEFGHIJ'),columns=['Python','Tensorflow','Keras'])
df.loc[['A','C','D','F']] # 选取指定⾏标签数据。
df.loc['A':'E',['Python','Keras']] # 根据⾏标签切⽚,选取指定列标签的数据
df.loc[:,['Keras','Tensorflow']] # :默认保留所有⾏
df.loc['E'::2,'Python':'Tensorflow'] # ⾏切⽚从标签E开始每2个中取⼀个,列标签进⾏切⽚ df.loc['A','Python'] # 选取标量值
print('-------------Part three:位置选择----------')
df.iloc[4] # ⽤整数位置选择。
df.iloc[2:8,0:2] # ⽤整数切⽚,类似NumPy
df.iloc[[1,3,5],[0,2,1]] # 整数列表按位置切⽚
df.iloc[1:3,:] # ⾏切⽚
df.iloc[:,:2] # 列切⽚
df.iloc[0,2] # 选取标量值
print('------------Part Four:boollean索引---------')
cond1 = df.Python > 100 # 判断Python分数是否⼤于100,返回值是boolean类型的Series
df[cond1] # 返回Python分数⼤于100分的⽤户所有考试科⽬数据
cond2 = (df.Python > 50) & (df['Keras'] > 50) # &与运算
df[cond2] # 返回Python和Keras同时⼤于50分的⽤户的所有考试科⽬数据
df[df > 50]# 选择DataFrame中满⾜条件的值,如果满⾜返回值,不然返回空数据NaN df[df.index.isin(['A','C','F'])] # isin判断是否在数组中,返回也是boolean类型值
print('------------Part Five:赋值操作-------------')
s = pd.Series(data = np.random.randint(0,150,size = 9),index=list('BCDEFGHIJ'),name = 'PyTorch')
df['PyTorch'] = s # 增加⼀列,DataFrame⾏索引⾃动对⻬
df.loc['A','Python'] = 256 # 按标签赋值
df.iloc[3,2] = 512 # 按位置赋值
df.loc[:,'Python'] = np.array([128]*10) # 按NumPy数组进⾏赋值
df[df >= 128] = -df # 按照where条件进⾏赋值,⼤于等于128变成原来的负数,否则不变 df
print('--------------多种实用筛选方式--------------')
from sklearn import datasets
import pandas as pd
boston = datasets.load_boston()
df = pd.DataFrame(boston.data, columns=boston.feature_names)
#筛选
第一种方式:[]
df[df['NOX']>df['NOX'].mean()].sort_values(by='NOX',ascending=False).head()#筛选出大于NOX这变量平均值的所有数据,然后按NOX降序排序
df[(df['NOX']>df['NOX'].mean())& (df['CHAS'] ==1)].sort_values(by='NOX',ascending=False).head()#再加上且条件CHAS为1,注意逻辑符号分开的条件要用()隔开
第二种方式:使用loc
df.loc[(df['NOX']>df['NOX'].mean()),['CHAS']] = 2#按条件筛选出数据,并筛选出指定变量,然后赋值
data1.loc[pd.isna(data1['new_Value']), 'new_Value'] = data1['Value']*beishu
第三种方式:isin
df.loc[df['NOX'].isin([0.538,0.713,0.437]),:].sample(5)#锁定某些具体的值的,这时候就需要isin了
df.loc[~df['NOX'].isin([0.538,0.713,0.437]),:].sample(5)#进行取反
第四种方式(针对字符串):str 和&
good_great_order = amazon_data[amazon_data['Text'].str.contains('good|great')] #good 或 great
no_good_order = amazon_data[~amazon_data['Text'].str.contains('good')] #不包含good
order = amazon_data[(amazon_data['Text'].str.contains('good|great'))&(amazon_data['日期date']>='2018-09-01')]
第五种方式:np.where
condition = df['A'] > 3
filtered_data = np.where(condition, df['A'], np.nan)# 大于 3 的元素保留,小于等于 3 的元素替换为 NaN
第六种方式:where/mask如果不满足匹配条件,就被赋值为默认的NaN或其他指定值
from sklearn import datasets
import pandas as pd
boston = datasets.load_boston()
df = pd.DataFrame(boston.data, columns=boston.feature_names)
cond = train['Sex'] == 'male'
train['Sex'].where(cond, inplace=True)
train.head()
#也可以用other赋给指定值。
cond = train['Sex'] == 'male'
train['Sex'].where(cond, other='FEMALE', inplace=True)
#写组合条件
train['quality'] = ''
traincond1 = train['Sex'] == 'male'
cond2 = train['Age'] > 25
train['quality'].where(cond1 & cond2, other='低质量男性', inplace=True)
第七种方式:query
# 常用方式
train[train.Age > 25]
# query方式
train.query('Age > 25')
train.query("Name.str.contains('William') & Age > 25")#注意条件里有''时,两边要用""包住
#query里还可以通过@来设定变量
name = 'William'
train.query("Name.str.contains(@name)")
第八种方式:filter是另外一个独特的筛选功能。filter不筛选具体数据,而是筛选特定的行或列
items:固定列名
regex:正则表达式
like:以及模糊查询
axis:控制是行index或列columns的查询
第九种方式:between 专门筛选数值范围的,就是between,用法很简单
diamonds[diamonds["price"]\
.between(3500, 3700, inclusive="neither")].sample(5)
squeeze
我们用.loc筛选想返回一个值,但返回的却是个series。其实,只要使用.squeeze()即可完美解决
# 没使用squeeze
subset = diamonds.loc[diamonds.index < 1, ["price"]]
# 使用squeeze
subset.squeeze("columns")
第四部分 数据清洗
实际上是数据预处理中的一些常用方法,在进行机器学习/深度学习之前,通常需要对数据进行去重/填充缺失值/异常值处理/标准化等动作。
df.columns = ['a','b','c']:重命名列名
pd.isnull():检查DataFrame对象中的空值,并返回一个Boolean数组
pd.notnull():检查DataFrame对象中的非空值,并返回一个Boolean数组
--------------------------------------判断空值-----------------------------------------------
pd.isnull(data.loc[i,'column_name'])==True
result.loc[pd.isnull(result['official_id'])==True] #选出有空值的,一定要astype 为float才能这样判断
--------------------------------------删除-----------------------------------------------
df.dropna():删除所有包含空值的行
df.dropna(axis=1):删除所有包含空值的列
df.dropna(axis=1,thresh=n):删除所有小于n个非空值的行
df.dropna(subset=['name', 'born']) #删除指定列有空值的
df.drop_duplicates() #删除全部值都重复的行
df.dropna(thresh=2)#保留少于两个缺失值的行
#drop指定包含字符串
zhuewang =zhuewang.drop(zhuewang.loc[(zhuewang['标题'].str.contains('玉米价格'))].index)
#删除指定列为0的行
cols_to_check=['home_pop_1','work_pop_1','live10','work10','first_rent','avg_consumption_1004']
dataresult11 =dataresult11.drop(dataresult11[(dataresult11[cols_to_check] == 0).any(axis=1)].index)
#指定列或者行过滤
df.drop(labels = ['price'],axis = 1)# 删除指定列
df.drop(labels = [0,1,5],axis = 0) # 删除指定⾏
--------------------------------------重复-----------------------------------------------
df.duplicated()#判断是否有重复项
df.drop_duplicates()#有重复项,则可以用drop_duplicates()移除重复项
df.drop_duplicates(subset=['A_ID', 'B_ID'], keep='first')#保留第一次
df.drop_duplicates(['a'])
--------------------------------------缺失值替换------------------------------------------
df.fillna(x):用x替换DataFrame对象中所有的空值
#缺失值替换
A列有空值,则用B列中对应的数据进行替换。理想前提是两个Series对象的索引是一致的,因为替换是根据索引来指定位置的
df["A"] = df["A"].combine_first(df["B"])
#使用loc对指定条件的缺失值替换
project_population.loc[pd.isnull(project_population['LivingPop3km']),'LivingPop3km']=project_population.loc[pd.isnull(project_population['LivingPop3km']),'LivingPop3km_avg']
--------------------------------------替换/重命名-----------------------------------------
s.replace(1,'one'):用‘one’代替所有等于1的值
s.replace([1,3],['one','three']):用'one'代替1,用'three'代替3
df.rename(columns=lambda x: x + 1):批量更改列名
df.rename(columns={'old_name': 'new_ name'}):选择性更改列名
df.set_index('column_one'):更改索引列
df = df.loc[:, ~df.columns.duplicated()] #删除重复列,注意pd.concat和append一定要注意列索引是否唯一
---------------------------------------检测异常值---------------------------------
df2 = pd.DataFrame(data = np.random.randn(10000,3),columns=['LotArea','te','hee']) # 正态分布数据
# 方法一:3σ过滤异常值,σ即是标准差
cond = (df2 > 3*df2.std()).any(axis = 1)
index = df2[cond].index # 不满⾜条件的⾏索引
df2.drop(labels=index,axis = 0) # 根据⾏索引,进⾏数据删
#方法二:四分箱线
out=[]
def iqr_outliers(df):
q1 = df.quantile(0.25)
q3 = df.quantile(0.75)
iqr = q3-q1
Lower_tail = q1 - 1.5 * iqr
Upper_tail = q3 + 1.5 * iqr
for i in df:
if i > Upper_tail or i < Lower_tail:
out.append(i)
print("Outliers:",out)
iqr_outliers(df2['LotArea'])
---------------------------------------行序反转----------------------------------
s2=s1.loc[::-1].head()
s2= s2.reset_index(drop=True).head()
--------------------------------------类型转换------------------------------------------
s.astype(float):将Series中的数据类型更改为float类型
new_list.select_dtypes('float').astype('int')将float的数据类型更改为int类型
new_list.select_dtypes(exclude='float').astype('int')将float的数据类型更改为int类型
第五部分 数据处理
对数据进行重塑、转换、排序、数学统计、分组聚合、集合合并等。
集成合并:append/concat/merge
重塑:unstack/stack ,.T
转换:map/apply/applymap/transform
print('------------------------------数据重塑--------------------------------')
df = pd.DataFrame(data = np.random.randint(0,100,size = (10,3)),
index = list('ABCDEFHIJK'),
columns=['Python','Tensorflow','Keras'])
df.T # 转置
df2 = pd.DataFrame(data = np.random.randint(0,100,size = (20,3)),
index = pd.MultiIndex.from_product([list('ABCDEFHIJK'),['期 中','期
末']]),#多层索引
columns=['Python','Tensorflow','Keras'])
df2.unstack(level = -1) # ⾏旋转成列,level指定哪⼀层,进⾏变换
df2.stack() # 列旋转成⾏
df2.stack().unstack(level = 1) # ⾏列互换
print('------------------------------数据排序--------------------------------')
df = pd.DataFrame(data = np.random.randint(0,30,size = (30,3)),index = list('qwertyuioijhgfcasdcvbnerfghjcf'),columns = ['Python','Keras','Pytorch'])
# 1.索引列名排序
df.sort_index(axis = 0,ascending=True) # 按索引排序,升序
df.sort_index(axis = 1,ascending=False) #按列名排序,降序
# 2.属性值排序
df.sort_values(by = ['Python']) #按Python属性值排序
df.sort_values(by = ['Python','Keras'])#先按Python,再按Keras排序
# 3.返回属性n⼤或者n⼩的值
df.nlargest(10,columns='Keras') # 根据属性Keras排序,返回⼤10个数据 df.nsmallest(5,columns='Python') # 根据属性Python排序,返回⼩5个数据
print('-----------------------------数学和统计方法---------------------------')
#简单统计
df = pd.DataFrame(data = np.random.randint(0,100,size = (20,3)),
index = list('ABCDEFHIJKLMNOPQRSTU'),
columns=['Python','Tensorflow','Keras'])
df.max(axis = 0) #轴0⼤值,即每⼀列⼤值
df.mean(axis = 1) #轴1平均值,即每⼀⾏的平均值
df.min() #默认计算轴0⼩值
#1.索引标签,位置获取
df['Python'].argmin() # 计算最⼩值位置
df['Keras'].argmax() # 最⼤值位置
df.idxmax() # 最⼤值索引标签
df.idxmin() # 最⼩值索引标签
# 2.更多统计指标
df['Python'].value_counts() # 统计元素出现次数
df['Keras'].unique() # 去重
df.cumsum() # 累加
print('------------------------------数据转换--------------------------------')
df = pd.DataFrame(data = np.random.randint(0,10,size = (10,3)),index = list('ABCDEFHIJK'),columns=['Python','Tensorflow','Keras'])
#1.map批量元素改变,Series专有
df['Keras'].map({1:'Hello',5:'World',7:'AI'}) # 字典映射
df['Python'].map(lambda x:True if x >=5 else False) # 隐式函数映
def convert(x): # 显示函数映射
if x%3 == 0:
return True
elif x%3 == 1:
return False
df['Tensorflow'].map(convert)
#2.apply 应⽤⽅法数据转换,通⽤
df['Keras'].apply(lambda x:True if x >5 else False)
#DataFrame,其中的x是DataFrame中列或者⾏,是Series
def convert(x): # ⾃定义⽅法
return (x.mean().round(1),x.count())
df.apply(convert,axis = 1) # ⾏平均值,计数
#apply进阶,搭配字典进行多条件的筛选过滤
filtered_dianping_group_[filtered_dianping_group_.apply(lambda x: (x['name'] in filter_dict) and (x['av_price'] in filter_dict[x['name']]) and (x['closed'] == 0),axis=1)]
#3.applymap DataFrame专有
df.applymap(lambda x : x + 100) # 计算DataFrame中每个元素
ran = np.random.permutation(10) # 随机重排
df.take(ran) # 重排DataFrame
df.take(np.random.randint(0,10,size = 15)) # 随机抽样
# 4.哑变量,独热编码,1表示有,0表示没有
df = pd.DataFrame({'key':['b','b','a','c','a','b']}) pd.get_dummies(df,prefix='',prefix_sep='')
print('-----------------------------分组聚合----------------------------------')
df = pd.DataFrame(data = {'sex':np.random.randint(0,2,size = 300),'class':np.random.randint(1,9,size = 300),'Python':np.random.randint(0,151,size = 300),'Keras':np.random.randint(0,151,size =300)})
# 1.先分组再获取数据
g = df.groupby(by = 'sex')[['Python','Java']] # 单分组
df.groupby(by = ['class','sex'])[['Python']] # 多分组
# 2.分组直接调⽤函数进⾏聚合
# 按照性别分组,其他列均值聚合
df.groupby(by = 'sex').mean().round(1) # 保留1位⼩数
# 按照班级和性别进⾏分组,Python、Keras的⼤值聚合
df.groupby(by = ['class','sex'])[['Python','Keras']].max()
# 按照班级和性别进⾏分组,计数聚合。统计每个班,男⼥⼈数
df.groupby(by = ['class','sex']).size()
# 基本描述性统计聚合
df.groupby(by = ['class','sex']).describe()
#聚合选择出组内排名最高的行
dianping_data_cal.loc[dianping_data_cal.groupby(['brand_id', 'shopuuid'])['rankings_paiming'].idxmax()]
# 3.apply和transform
#apply 里面可以直接写统计函数/也可以自定义写统计需求,得到的将是一个 新的Series 或 DataFrame。
df.groupby(by = ['class','sex'])[['Python','Keras']].apply(np.mean).round(1)
dianping_poi_brand_polygon_calculate=dianping_poi_brand_polygon.groupby(['grid_polygon']).apply(lambda x:pd.Series({'avg_exponent':np.sum(x['avg_exponent']),'all_chain_brand_count':len(x)})).reset_index()
def mean_ignore_none(values):
non_none_values = [value for value in values if value !=0]
return np.nanmean(non_none_values) if non_none_values else None
mean_starScore = brand_stores_data.groupby('group_clean_name')
['starScore'].apply(mean_ignore_none).reset_index()
#apply进阶:
#(1)添加条件判断进行不同聚合
project_brand_format_population = project_brand_tag.groupby(['project_id', xf_format_name]).apply(lambda x: np.sum(x['brand_population']) if (x['one_format_id'] == 1001).any() else np.mean(x['brand_population'])).reset_index(name='format_population')
#(2)使用相同函数组合多个字段
def agg_func(datas):
non_zero_values = {data for data in datas if data != '0' and not pd.isna(data)}
return non_zero_values if non_zero_values else None
shopuuid_bangdan_group=shopuuid_bangdan.groupby('shopuuid').apply(lambda group: agg_func(group['rankings'].tolist() + group['shopRankTag'].tolist() + group['heizhenzhu'].tolist())).reset_index()
#transforms 返回全数据,返回DataFrame.shape和原DataFrame.shape⼀样。
def normalization(x):
return (x - x.min())/(x.max() - x.min()) # ⼤值⼩值归⼀化
df.groupby(by = ['class','sex']) [['Python','Tensorflow']].transform(normalization).round(3)
#筛选出在各个 'grid_polygon' 分组中只出现一次的 'project_name' 所对应的行数据。
filter_data.groupby('grid_polygon')['project_name'].transform('count') == 1)
citycircle_shp['比例']=citycircle_shp.groupby('functional_classification')['functional_classification'].transform(lambda x: x.count() / len(citycircle_shp) * 100)
#4.agg
# 分组后调⽤agg应⽤多种统计汇总
df.groupby(by = ['class','sex']) [['Tensorflow','Keras']].agg([np.max,np.min,pd.Series.count])
# 分组后不同属性应⽤多种不同统计汇总
df.groupby(by = ['class','sex'])[['Python','Keras']].agg({'Python':[('⼤值',np.max),('⼩值',np.min)], 'Keras':[('计数',pd.Series.count),('中位数',np.median)]}
#聚合后直接对组内的不同属性应用不同统计汇总
df.groupby(by = ['class','sex']).agg('python⼤ 值'=('Python',np.max),
'Keras计数'=('Keras','count')).reset_index()
#5.pivot_table
def count(x):
return len(x)
df.pivot_table(values=['Python','Keras','Tensorflow'],index=['class','sex'], aggfunc={'Python':[('⼤值',np.max)],'Keras':[('⼩值',np.min),('中位数',np.median)], 'Tensorflow':[('⼩值',np.min),('平均值',np.mean),('计 数',count)]})
#进阶:加入条件判断的统计
pandas_data_group=pandas_data.groupby(['name', 'category']).agg(count=('shopuuid', 'count'),closed0=('closed', lambda x: (x == 0).sum()),closed1=('closed',lambda x:(x==1).sum())).reset_index()
print('---------------------------------集成合并----------------------------------')
df1 = pd.DataFrame(data = np.random.randint(0,150,size = [10,3]),
index = list('ABCDEFGHIJ'),# ⾏标签,⽤户
columns=['Python','Tensorflow','Keras']) # 考试科⽬
df2 = pd.DataFrame(data = np.random.randint(0,150,size = [10,3]),
index = list('KLMNOPQRST'),
columns=['Python','Tensorflow','Keras']) # 考试科⽬
df3 = pd.DataFrame(data = np.random.randint(0,150,size = (10,2)),
index = list('ABCDEFGHIJ'),
columns=['PyTorch','Paddle'])
#1.append
df1.append(df2)#将df2中的行添加到df1的尾部
d=[df1,df2,df3]
#2.concat
df_=pd.concat(d, axis = 1)#concat还可实现多表合并,横向合并,axis=0,默认是行方向上堆叠
#3.merge
# 创建第一个 DataFrame
df1 = pd.DataFrame({'employee': ['Bob', 'Jake', 'Lisa', 'Sue'],
'group': ['Accounting', 'Engineering', 'Engineering', 'HR']})
# 创建第二个 DataFrame
df2 = pd.DataFrame({'employee': ['Lisa', 'Bob', 'Jake', 'Sue','Victora'],
'hire_date': [2004, 2008, 2012, 2014,2018]})
df3=pd.merge(df1,df2,on = 'employee',how = 'outer')
df4=pd.merge(df1,df2, on='employee', how='inner').sort_values('hire_date',ascending=True)
sql 查询
sql 查询案例
SELECT `name`, COUNT(*) AS name_count
FROM (
select `name` from dianping_shop_2023_group_format where `name` in(SELECT d.`name`
FROM (
SELECT DISTINCT b.`name`, b.shopuuid,b.backCategoryName,b.closed,b.avgPrice
FROM dianping_shop_2023 b
INNER JOIN dianping_shop_2023_group a
ON b.`name` = a.`name` AND b.backCategoryName = a.category
INNER JOIN dianping_shop_2023_group_format af
ON a.`name` = af.`name` AND a.one_format = af.one_format
WHERE a.one_format = '餐饮'
AND b.closed IS NOT NULL) AS d
GROUP BY d.`name`
HAVING AVG(d.avgPrice) <> 0) and one_format='餐饮'
) AS name_counts
GROUP BY `name`
HAVING name_count > 1;
窗口函数案例
select a.*,b.count,all_num,closed0_num,closed1_num
from (
WITH category_counts AS (SELECT `name`, `backCategoryName`, COUNT(*) AS category_count,ROW_NUMBER() OVER(PARTITION BY `name` ORDER BY COUNT(*) DESC) AS rn FROM `dianping_shop_2023_clean`
WHERE `name` IN (SELECT `name`FROM `dianping_shop_2023_group` WHERE one_format = '餐饮' GROUP BY `name` HAVING SUM(count) > 1)GROUP BY `name`, `backCategoryName`)
SELECT `name`,`backCategoryName`,category_count FROM category_counts WHERE rn = 1 ORDER BY `name`)a
left join (
SELECT `name`, COUNT(*) AS count,sum(count) as all_num, sum(closed0)as closed0_num,sum(closed1) as closed1_num FROM `dianping_shop_2023_group` WHERE one_format = '餐饮' GROUP BY `name` HAVING sum(count) > 1) b
on a.`name`=b.`name`