- 什么是Pandas
- 一、如何读取数据库-read_sql
- 二、如何筛选数据
- 三、如何连表-merge
- 四、如何删除一行或一列-drop
- 五、如何分组统计-groupyby
- 六、如何排序-sort_values/sort_index
- 七、如何重建索引-groupby(as_index=False)/reset_index
- 八、如何翻转dataframe-T
- 九、如何重命名列-rename
- 十、如何强制转换类型-astype
- 十一、如何在只有一列的情况下groupby并count-size
- 十二、如何操作时间-.dt.
- 十三、如何操作字符串-.str.
- 十四、如何进行数据透视-pivot/pivot_table
- 十五、如何进行可视化-plot
- 十六、如何应用函数和映射
- 十七、如何处理缺失数据
- 十八、如何使用多级索引
- 十九、如何删除重复数据-drop_duplicated
- 二十、如何替换值-replace
- 二十一、如何连接两个dataframe-concat
- 二十二、如何重新设置索引-reindex
- 二十二、如何重新采样-resample
- 二十三、如何打补丁-combine_first
- 二十四、如何进行排名-rank
- 二十五、如何应用函数修改原dataframe-指定参数inplace
什么是Pandas
Pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。
Pandas纳入了大量库和一些标准的数据模型,提供了大量能使我们快速便捷地处理数据的函数和方法。
主要包含两种数据类型:Series和DataFrame
- Series可以理解为dict的升级版本,主数组存放numpy数据类型,index数据存放索引
- DataFrame相当于多维的Series,有两个索引数组,分别是行索引和列索引,可以理解成Series组成的字典
相关帮助文档
一、如何读取数据库-read_sql
示例代码如下
from sqlalchemy import create_engine
import pandas as pd
username = \'用户名\'
password = \'密码\'
host = \'连接地址\'
db = \'数据库\'
port = 端口号
link = f\'\'\'mysql+pymysql://{username}:{password}@{host}:{port}/{db}?charset=utf8\'\'\'
engine = create_engine(link, pool_recycle=3600)
核心方法read_sql
log:pd.DataFrame = pd.read_sql("SELECT * FROM log ORDER BY id DESC ",engine)
执行结果如下
二、如何筛选数据
- 筛选创建时间大于某个时间点的记录
import datetime
log[log[\'create_time\'] > \'2020-01-15 16:14:22\']
- 筛选指定列的DataFrame
直接传递数组给给DataFrame
logs[[\'user_id\',\'type\']]
- 获取一列Series
logs[\'type\']
- iloc和loc
iloc[行,列]是根据行号和列号获取,loc[行索引 ,列索引]是根据索引名获取
三、如何连表-merge
现在我需要将user_id对应的用户名找出来,示例代码如下
#查询出所有的用户,以便将log和users做join
users:pd.DataFrame=pd.read_sql("SELECT * FROM users",engine)
users
*
users和log的字段太多,先做一下筛选
log=log[[\'type\',\'user_id\',\'project_id\',\'create_time\']]
users=users[[\'id\',\'username\',\'real_name\']]
执行join,使用merge方法,how指定左连,left_on指定左表使用的字段, right_on指定右表使用的字段
log.merge(users,how=\'left\',left_on=\'user_id\',right_on=\'id\')
四、如何删除一行或一列-drop
drop方法,axis为0代表行,1代表列
renameRes.drop(\'创建时间\',axis=1)
五、如何分组统计-groupyby
dropRes.groupby([\'type\',\'real_name\']).count()
groupby也可以可以传入一个能够访问索引上字段的函数
rng=pd.date_range(\'1/1/2020\',periods=100,freq=\'D\')
ts=pd.Series(np.random.randn(len(rng)),index=rng)
ts.groupby(lambda x:x.month).mean()
2020-01-31 0.182420
2020-02-29 0.200134
2020-03-31 -0.108818
2020-04-30 -0.187426
Freq: M, dtype: float64
六、如何排序-sort_values/sort_index
by指定字段,ascending指定升序还是降序
log.sort_values(by=\'user_id\',ascending=False)
七、如何重建索引-groupby(as_index=False)/reset_index
默认groupby后的结果是行索引是groupby的字段
log.merge(users,how=\'left\',left_on=\'user_id\',right_on=\'id\').groupby(\'type\').count()
groupby指定参数as_index
log.merge(users,how=\'left\',left_on=\'user_id\',right_on=\'id\').groupby(\'type\',as_index=False).count()
另外,还可以count完后直接调用reset_index方法
log.merge(users,how=\'left\',left_on=\'user_id\',right_on=\'id\').groupby(\'type\').count().reset_index()
八、如何翻转dataframe-T
log.T
九、如何重命名列-rename
使用rename方法,传递一个字典即可,如下
pd.DataFrame = res[[\'type\',\'username\',\'real_name\',\'create_time\']].rename({\'create_time\':\'创建时间\'},axis=1)
十、如何强制转换类型-astype
log[\'create_time\'].astype(str)
十一、如何在只有一列的情况下groupby并count-size
count是必须依赖其他列做统计的,当只有一列的时候如何还使用count,是看不出统计字段的,正确的方法应该是使用size
test4=pd.read_sql("SELECT `type` FROM log LIMIT 100",engine)
test4.groupby(\'type\').size()
十二、如何操作时间-.dt.
例如,要将create_time转为YY-MM-DD格式,可以使用函数.dt.date
log[\'create_time\'].dt.date
具体方法可以参考Series的API文档的Datetime操作
十三、如何操作字符串-.str.
例如,转为大写
log[\'type\'].str.upper()
具体方法可以参考Series的API文档的字符串操作
十四、如何进行数据透视-pivot/pivot_table
简单的理解就是一个更高级的groupby功能
df = pd.DataFrame({\'foo\': [\'one\', \'one\', \'one\', \'two\', \'two\',
\'two\'],
\'bar\': [\'A\', \'B\', \'C\', \'A\', \'B\', \'C\'],
\'baz\': [1, 2, 3, 4, 5, 6],
\'zoo\': [\'x\', \'y\', \'z\', \'q\', \'w\', \'t\']})
df.pivot(index=\'foo\', columns=\'bar\', values=\'baz\')
pivot_table支持分组后再聚合操作
df = pd.DataFrame({"A": ["foo", "foo", "foo", "foo", "foo",
"bar", "bar", "bar", "bar"],
"B": ["one", "one", "one", "two", "two",
"one", "one", "two", "two"],
"C": ["small", "large", "large", "small",
"small", "large", "small", "small",
"large"],
"D": [1, 2, 2, 3, 3, 4, 5, 6, 7],
"E": [2, 4, 5, 5, 6, 6, 8, 9, 9]}
)
根据ABC分组,计算D的值,AB为行索引,C为列索引再使用sum函数,如下
df.pivot_table(values=\'D\', index=[\'A\', \'B\'], columns=[\'C\'], aggfunc=np.sum, fill_value=0)
十五、如何进行可视化-plot
一般使用matplotlib进行绘图
例如,统计所有的操作日志最多的前10个绘制直方图
先取出这些数据,如下
#获取所有操作类型最多的10条数据
countRes=log.groupby(\'type\',as_index=False).count().drop([\'create_time\',\'project_id\'],axis=1).rename({\'user_id\':\'count\'},axis=1).sort_values(by=\'count\',ascending=False).head(10)
为了让图是递增的状态,我们反转一下
countRes=countRes.iloc[::-1]
再使用matplotlib绘制直方图
import matplotlib.pyplot as plt
plt.barh(countRes[\'type\'],countRes[\'count\'])
十六、如何应用函数和映射
-
apply(DataFrame)
DataFrame的函数,apply将函数应用到由各列或行所形成的一维数组上,默认是传入列的Series,可以指定axis=1传入行
-
applymap(DataFrame)
DataFrame的函数,对每个元素应用函数
-
map/apply(Series)
对应Dataframe的applymap
十七、如何处理缺失数据
pands使用NaN(Not a Number)表示缺失数据,处理方法有
- dropna:对轴标签进行过滤
- fillna:用指定值或插值方法(如ffill或bfill)填充缺失数据
- isnull:返回一个含有布尔值的对象
- notnull:isnull的否定形式
十八、如何使用多级索引
- Series多级索引
data = pd.Series(np.random.randn(10),
index=[
[\'a\',\'a\',\'a\',\'b\',\'b\',\'b\',\'c\',\'c\',\'d\',\'d\'],
[1, 2, 3, 1, 2, 3, 1, 2, 2, 3]
]
)
选取一个子集
data[\'b\']
选取多个子集
data[\'b\':\'c\']
选取内层:,号后面添加行号
data[:,2]
- Series和DataFrame互转
#Series转换为DataFrame
data.unstack()
#将DataFrame转换为一个Series
data.unstack().stack()
- DataFrame的多级索引
frame=pd.DataFrame(np.arange(12).reshape((4,3)),
index=[
[\'a\',\'a\',\'b\',\'b\'],
[1,2,1,2]
],
columns=[
[\'Ohio\',\'Ohio\',\'Colorado\'],
[\'Green\',\'Red\',\'Green\']
],
)
- 给索引命名
frame.index.names=[\'key1\',\'key2\']
frame.columns.names=[\'state\',\'color\']
- swaplevel:重排分级顺序,互换级别的对象
frame.swaplevel(\'key1\',\'key2\')
- sort_index:根据单个级别中的值对数据进行反序
frame.sort_index(level=0,ascending=False)
- set_index:将其一个或多个列转换为行索引,并创建一个新的DataFrame
df=pd.DataFrame({
\'a\':range(7),
\'b\':range(7,0,-1),
\'c\':[\'one\',\'one\',\'one\',\'two\',\'two\',\'two\',\'two\'],
\'d\':[0,1,2,0,1,2,3]
})
df.set_index([\'c\',\'d\'])
- reset_index:功能和set_index相反,层次化索引的级别会被转移到列里面
十九、如何删除重复数据-drop_duplicated
data=pd.DataFrame({
\'k1\':[\'one\']*3 + [\'two\']*4,
\'kw\':[1,1,2,3,3,4,4]
})
data.drop_duplicates()
二十、如何替换值-replace
df = pd.DataFrame({\'foo\': [\'one\', \'one\', \'one\', \'two\', \'two\',
\'two\'],
\'bar\': [\'A\', \'B\', \'C\', \'A\', \'B\', \'C\'],
\'baz\': [1, 2, 3, 4, 5, 6],
\'zoo\': [\'x\', \'y\', \'z\', \'q\', \'w\', \'t\']})
替换A和B为chenqionghe,第一个参数为查找值,第二个参数为替换的值
df.replace([\'A\',\'B\'],\'chenqionghe\')
也可以传入字典,替换多个值
df.replace({\'A\':\'cqh\',\'B\':\'chenqionghe\'})
二十一、如何连接两个dataframe-concat
df1=DataFrame(np.arange(6).reshape(3,2),
index=list(\'abc\'),
columns=[\'one\',\'two\']
)
df2=DataFrame(5+np.arange(4).reshape(2,2),
index=list(\'ac\'),
columns=[\'three\',\'four\']
)
列拼接
pd.concat([df1,df2],sort=False)
行拼接
pd.concat([df1,df2],axis=1,sort=False)
二十二、如何重新设置索引-reindex
frame=pd.DataFrame(np.arange(9).reshape((3,3)),
index=[\'a\',\'b\',\'c\'],
columns=[\'light\',\'weight\',\'baby\']
)
#默认修改行索引
frame2=frame.reindex([\'a\',\'b\',\'c\',\'d\'])
#同时修改行索引和列索引
frame.reindex(index=[\'a\',\'b\',\'c\',\'d\'],columns=[\'light\',\'gym\',\'muscle\'])
二十二、如何重新采样-resample
创建3个周三的时间序列
ts1=pd.Series(
np.random.randn(3),
index=pd.date_range(\'2020-6-13\',periods=3,freq=\'W-WED\')
)
升采样转为每个工作日
ts1.resample(\'B\').asfreq()
指定为ffill的填充
ts1.resample(\'B\').ffill()
二十三、如何打补丁-combine_first
combine_first相当于用参数对象中的数据为调用者对象的缺失数据”打补丁“
df1=pd.DataFrame({
\'a\':[1,np.nan,5,np.nan],
\'b\':[np.nan,2,np.nan,6],
\'c\':range(2,18,4)
})
df2=pd.DataFrame({
\'a\':[5,4,np.nan,3,7],
\'b\':[\'chenqionghe\',3,4,6,8]
})
然后我们可以用df2的值给d1打补丁,如下
df1.combine_first(df2)
二十四、如何进行排名-rank
a=pd.DataFrame(np.arange(60).reshape(10,6),columns=[\'a\',\'b\',\'c\',\'d\',\'e\',\'f\'])
默认是对行进行排序,如下
a.rank()
可以传axis=1对列进行排序
a.rank(axis=1)
默认是升序,可以传入ascending=False进行降序
a.rank(ascending=False)
二十五、如何应用函数修改原dataframe-指定参数inplace
pandas 中 inplace 参数在很多函数中都会有,它的作用是:是否在原对象基础上进行修改
- inplace = True:不创建新的对象,直接对原始对象进行修改;
- inplace = False:对数据进行修改,创建并返回新的对象承载其修改结果。
默认是False,即创建新的对象进行修改,原对象不变,和深复制和浅复制有些类似。