之前看了numpy,这两天看了pandas,也在这里整理一下。

新建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import	pandas as pd

data = {
'key1':['value11,value12'],
'key2':['value21','value22']
}
df = pd.DataFrame(data)

df.index#描述dataframe的index的【开始/结束)和步长,注意这个是指df的index而非数据的id
df.columns#行名
df.dtypes#类型
df.size#数据总数
df.shape#数据形式(行,列)
df.ndim#维度
df.T#转置

从数据库中得到数据 && 将数据写入数据库

1
2
3
4
5
6
7
8
9
10
11
from sqlalchemy import create_engine

#连接mysql数据库
engine = create_engine('mysql+pymysql://root:qh129512@127.0.0.1:3306/testdb?charset=utf8')

sql = 'select * from person'

#下面有三种获取数据的方式,返回的formlist就是一个dataframe
formlist = pd.read_sql_query(sql,con=engine)#参数为sql语句
formlist = pd.read_sql_table(table,con=engine)#参数为表名
formlist = pd.read_sql(sql,con=engine)#参数可以是sql语句,也可以表名

下面是将数据写入数据库

1
2
3
4
5
df = pd.DataFrame(data,columns=['name,birthday'])#这里的columns就是指dataframe里有哪些comlumn,这里没有的df里也不会有,如果不添加columns这个参数就默认data中全部数据

df.to_sql(name='person',con=engine, if_exists='append',index=False)
#if_exists:有三种fail->表存在就不写入;replace->表存在就删掉原来的表重新创建;append->在原表基础上追加数据。默认为fail
#index:决定是否将行索引作为数据传入数据库,注意:如果数据库没有专门来存这个的就false,因为表里没有这里用true会有问题

使用dataframe

直接取某个、某些数据

1
2
3
4
df['name'][0]
df.name[:5]
df[['name','birthday']][:2]
df.head()

取数据的切片

1
2
3
4
5
6
7
df.loc[:5,'name']#前一个参数为行索引,后一个是列索引名称
df.iloc[0:2,1]

#有条件的切片
df.loc[(df['name'] == 'max'),:]#取name为max的切片

df.iloc[(df['name'] == 'max').values,:]

这里有两个函数,loc和iloc,区别有

  • loc第一个参数可以为series,例如我传入一个条件,其实相当于一个Series([True,True,False…])这种形式;iloc不可以穿series,但能传一个array,所以可以通过.values的形式传入条件
  • 行索引时loc是前后闭区间,而iloc是前闭后开区间(python中这种更常见)

删除数据

1
2
3
4
5
6
df.drop(labels=rang(9,10),axis=0,inplace=True)
'''
labels接收string、array,表示删除行/列的标签
axis接收0、1,表示操作轴向,0为横,1为纵
inplace接收boolean,代表操作是否对原数据生效
'''

对dataframe中数据修改

1
2
3
4
5
#直接声明就可以添加一列,如
df['prefix_name'] = 'MAC_' + df['name']

#修改某个数据可以将其找出来然后直接赋值
df.loc[(df.name == 'max'),'name'] = 'maxhh'

随机数的使用

1
2
3
4
series = pd.Series(np.random.randint(high=10000,low=1000,size=8))#产生一个随机series


df.loc[:,'net-worth'] = series#将series值付给df

dataframe算数统计

1
2
3
4
5
df['net-worth'].mean()#平均值
np.mean(df['net-worth'])#另一种计算平均值的方法
df['net-worth'].min()#最小值
df['net-worth'].describe()#描述,包含很多数据可以用!
nullNum = df.shape[0] - df['name'].count()#统计有多少空值

Category类型的使用

可以将某一列转化成category类型,这样相当于做了一次分类处理,这样得到的描述性信息会很多

1
2
3
df['name'] = df['name'].astype('category')#注意这里是赋值而不是调用

df['name'].describe()

时间类型

pandas里有很多时间类型,不同类型用处不同。如timestamp主要用来记录时间,而timedelta用来做时间运算

1
2
#有很多方法创建或转化出一个timestamp
today_date = pd.to_datetime('2018-8/5')#随意的一个string都可以识别

注意一个概念,从数据库一个datatime拿出来的时间如果调用dtype的话发现是(‘<M8[ns]’)类似的类型,展开来说:

这个是属于机器的比较特别的类型:
小端机器的类型:datatime[ns] == <M8[ns]
大端机器的类型:datatime[ns] == >M8[ns]
这个可以通过

1
2
np.dtype('datetime64[ns]') == np.dtype('<M8[ns]')
#out: True

证明。
所以当数据库中取出就是这种类型时,不需要再进行处理,但如果取出是个object,则用pd.to_datatime处理

1
df['birthday'] = pd.to_datatime(df['birthday'])

这里要熟悉的操作有:

1
2
3
user_birthday = [i.year for i in df['birthday']]#返回所有年份的list

birthday = df[df['birthday']<=pd.datetime(1991,1,1)]#按条件取时间时,一定要那拿timestamp与对应的pdf.datetime()相比

还有时间做加减法也是支持的,timestamp可以加一个tmiedelta来做时间的计算。注意timedelta的参数为weeks,days,hours以及更小的时间
直接用+,-符号就可以做计算了。相反的,想算两个时间差,只要用两个datetime做减法,即可得到timedelta类型的时间差距

1
2
3
4
5
aweek_after = date + pd.Timedelta(weeks = 1)

today_date = pd.to_datetime('2018-8-5')

time_delta = aweek_after - today_date#两个timestamp做减法,得到了一个timedelta类型的时间差

分组和聚合

分组顾名思义,就是将数据按照一定条件进行分组,得到数据整体情况

1
2
data_group = df.groupby(by='birthday')
data_group.count()

这里的count()得到如下表结果

id name net-worth
birthday
1987-01-10 1 1 1
1989-03-10 6 0 4
1993-08-05 1 1 1
1995-12-12 1 1 1
1996-10-12 1 1 1

分组的直接结果并不能直接看,因为它返回的只是一个地址,但可以方便的查分组后的一些属性,如:count,head,max等等

聚合,就是将一组数据做aggretate,聚合的函数自己定

1
2
3
df['net-worth'].agg([np.sum,np.mean])#针对net-worth数据计算两种agg,分别以sum和mean

df.agg({'net-worth':[np.sum,sp.mean]})#针对不同数据要进行不同的agg,可以用key-value的方式

agg函数的参数是计算函数,这个函数可以用numpy中一些简单的统计函数,如果复杂也可以自定义,如:

1
2
3
4
5
6
7
def Trinum(data):
return data.sum()*2

df['net-worth'].agg(Trinum)#agg函数的参数可以是函数,该函数将data传入做处理,然后返回即可
#稍微注意下sum后面的括号,没有括号是函数,有括号的是执行,但必须声明参数

df['net-worth'].agg(lambda x:x*2)#agg的参数可以是lambda函数

这里的一个例子:

1
df.groupby(by='birthday').agg(np.mean)#完全等价于data_group.mean(),都是求每组的平均值

当然,apply函数、transform函数和agg函数也大部分相同,但apply方法不能用key-value类型来特定的处理,transform方法只有一个参数function

创建透视表

可以通过pandas创建透视表

1
pd.pivot_table(df[['id','name','net-worth']],index=['id'],columns='name',fill_value=0)#不显示无index的值

得到

net-worth
name hape john johnny max
id
1 0 0 0 6355
2 0 6567 0 0
4 0 0 8491 0
8 6872 0 0 0

但这不是pandas的重点,略~