10分钟了解pandas

本篇文章主要是针对pandas的基础运用,做简单的记录汇总,加深印象,以官方网站的api做练习。
官方网址:http://pandas.pydata.org/pandas-docs/stable/10min.html
主要包括DataFrame、Series数据类型的切片取值、索引取值、缺失值处理、筛选、更改值、填充、关联、合并、append、分组、以及stack、unstack,和透视表用法,以及运算、画图、时间序列。。这些用法算是pandas入门最基本的掌握,后面会继续学习高级的pandas用法,因为pandas处理数据真的太强大了,下次会举些项目例子

# 导入需要的包
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# np.nan是数值型,pd.NaT是object类型
s = pd.Series([1,3,5,np.nan,6,8])

下面图片可以看到具体生成s的数据类型


# 利用datetime数据格式做索引,创建DataFrame。
dates = pd.date_range('20130101', periods=6)
df = pd.DataFrame(np.random.randn(6,4), index=dates, columns=list('ABCD'))
# 利用dict数据对象创建DataFrame,注意pd.Timestamp和pd.Categorical这两个对象
df2 = pd.DataFrame({ 'A' : 1.,
                         'B' : pd.Timestamp('20130102'),
                         'C' : pd.Series(1,index=list(range(4)),dtype='float32'),
                         'D' : np.array([3] * 4,dtype='int32'),
                         'E' : pd.Categorical(["test","train","test","train"]),
                         'F' : 'foo' })
# 结果如下:
df2
Out[11]: 
     A          B    C  D      E    F
0  1.0 2013-01-02  1.0  3   test  foo
1  1.0 2013-01-02  1.0  3  train  foo
2  1.0 2013-01-02  1.0  3   test  foo
3  1.0 2013-01-02  1.0  3  train  foo
# 每一列的数据类型查看
df2.dtypes
Out[12]: 
A           float64
B    datetime64[ns]
C           float32
D             int32
E          category
F            object(字符串是object型)
dtype: object

查看数据

# 默认是前5行数据
df.head()
# 指定最后3行数据
df.tail(3)
# 查看索引
df.index
# 查看所有列名
df.columns
# 查看值
df.values
# 展示DataFrame的数据统计情况,包括计数、平均值、最小值、最大、标准差等数据指标
df.describe()
# 数据转置查看,也就是原来的列成为索引,原来的索引成为列
df.T
# 根据某一轴,索引排序,下面选axis=1是根据列名排序,ascending=False表示降序,ascending=True表示升序
df.sort_index(axis=1, ascending=False)
# 根据某一列,值排序,下面以列名B值进行排序,默认是升序,从小到大
df.sort_values(by='B')

筛选数据

# 选择某一列
df['A']
# 选择某些行,比如下面选择索引是0,1,2,也就是前三行,因为虽然索引是其他标记别名,其实内部还是以0,1,2,3……的索引,所以就可以根据0,1,2等或者切片去选择行
df[0:3]
# 同理,用已有的索引名获取第2行、第3行,第4行,发现了没有,如果用默认的0,1,2,3……,切片时不含尾标的,但用已有的索引名,切片时含有尾标。你可以打印查看
df['20130102':'20130104']
####  
# 选择某一行,如果你用df[0]就会报错了,这个可不是选择第一行啊。df.loc[0]也会报错,df.iloc[0]才是正确的。后面介绍df.loc和df.iloc的区别
df.loc[dates[0]]     # 正确,因为dates[0]是已定义的索引别名,而如果用df.loc[0]就错误,当然df.iloc[0]这个是可以用默认的0,1,2等索引,是正确的。
df.iloc[0]  # 正确,但df.iloc[dates[0]]就错误了,这个说明了df.iloc和df.loc的区别
# 行和列同时选
df.loc[:,['A','B']]
df.loc['20130102':'20130104',['A','B']]
df.loc[dates[0],'A'] 和 df.at[dates[0],'A'] 等同,只不过df.at更快的获取该值,并且df.at不支持获取多个值。
# 和前面介绍的一样,df.loc和df.iloc的区别,df.iloc只能用默认的索引和列名,也就是0,1,2,3,4……
df.iloc[3:5,0:2]
df.iloc[[1,2,4],[0,2]]
df.iloc[1:3,:]
df.iloc[:,1:3]
df.iloc[1,1] 和 df.iat[1,1] 等同
#############################
# 根据布尔类型筛选数据
# 根据某列大于某值做判断筛选,其实就是一列布尔类型值代入到DataFrame中筛选
df[df.A > 0]
Out[39]: 
                   A         B         C         D
2013-01-01  0.469112 -0.282863 -1.509059 -1.135632
2013-01-02  1.212112 -0.173215  0.119209 -1.044236
2013-01-04  0.721555 -0.706771 -1.039575  0.271860
# 根据DataFrame的值做判断筛选,这是满足条件就筛选出来,不满足就会变为NaN
df[df > 0]
Out[40]: 
                   A         B         C         D
2013-01-01  0.469112       NaN       NaN       NaN
2013-01-02  1.212112       NaN  0.119209       NaN
2013-01-03       NaN       NaN       NaN  1.071804
2013-01-04  0.721555       NaN       NaN  0.271860
2013-01-05       NaN  0.567020  0.276232       NaN
2013-01-06       NaN  0.113648       NaN  0.524988
# 复制df
df2 = df.copy()
# 对df2新增一列
df2['E'] = ['one', 'one','two','three','four','three']
# 根据isin判断做筛选,其实还是某一列的
df2[df2['E'].isin(['two','four'])]

更改值

s1 = pd.Series([1,2,3,4,5,6], index=pd.date_range('20130102', periods=6))
# 下面就把列名F值去改变,赋值是Series数据
df['F'] = s1
# 同样,把列名'D'去改变,赋值np.array数据
df.loc[:,'D'] = np.array([5] * len(df))
# 根据索引➕列名去更改某一个值
df.at[dates[0],'A'] = 0
# 根据默认索引➕列名去更改某一值
df.iat[0,1] = 0
# 根据条件去更改值
df2 = df.copy()
df2[df2 > 0] = -df2

缺失数据

# 缺失数据一般用np.nan表示,默认情况不会参与计算

# 改变df的索引,列名,生成新的DataFrame数据
df1 = df.reindex(index=dates[0:4], columns=list(df.columns) + ['E'])
# 对0,1行,E列对应的数据更改数据值
df1.loc[dates[0]:dates[1],'E'] = 1
df1
Out[57]: 
                   A         B         C  D    F    E
2013-01-01  0.000000  0.000000 -1.509059  5  NaN  1.0
2013-01-02  1.212112 -0.173215  0.119209  5  1.0  1.0
2013-01-03 -0.861849 -2.104569 -0.494929  5  2.0  NaN
2013-01-04  0.721555 -0.706771 -1.039575  5  3.0  NaN
# dropna函数功能:丢弃缺失值,参数how=‘any’只要任一行存在缺失值,就丢弃。
df1.dropna(how='any')
Out[58]: 
                   A         B         C  D    F    E
2013-01-02  1.212112 -0.173215  0.119209  5  1.0  1.0
# fillna函数对缺失值填充
df1.fillna(value=5)
Out[59]: 
                   A         B         C  D    F    E
2013-01-01  0.000000  0.000000 -1.509059  5  5.0  1.0
2013-01-02  1.212112 -0.173215  0.119209  5  1.0  1.0
2013-01-03 -0.861849 -2.104569 -0.494929  5  2.0  5.0
2013-01-04  0.721555 -0.706771 -1.039575  5  3.0  5.0
# isna判断缺失值
pd.isna(df1)
Out[60]: 
                A      B      C      D      F      E
2013-01-01  False  False  False  False   True  False
2013-01-02  False  False  False  False  False  False
2013-01-03  False  False  False  False  False   True
2013-01-04  False  False  False  False  False   True

运算

# 列的平均值,如果是行的平均值,参数axis=1即可,默认是0
df.mean()
Out[61]: 
A   -0.004474
B   -0.383981
C   -0.687758
D    5.000000
F    3.000000
dtype: float64
# axis=1的情况
df.mean(1)
Out[62]: 
2013-01-01    0.872735
2013-01-02    1.431621
2013-01-03    0.707731
2013-01-04    1.395042
2013-01-05    1.883656
2013-01-06    1.592306
Freq: D, dtype: float64

# 值推移
s = pd.Series([1,3,5,np.nan,6,8], index=dates).shift(2)
# 可以看到原2013-01-01、2013-01-02索引 对应的值向下推移了2行,同时nan值补充上。
 s
Out[64]: 
2013-01-01    NaN
2013-01-02    NaN
2013-01-03    1.0
2013-01-04    3.0
2013-01-05    5.0
2013-01-06    NaN
Freq: D, dtype: float64
# DataFrame数据与Series数据做运算,用到广播概念,sub是相减
df.sub(s, axis='index')

apply函数

默认在列上

df.apply(np.cumsum)

df.apply(lambda x: x.max() - x.min())
统计值出现的次数

s = pd.Series(np.random.randint(0, 7, size=10))
s
Out[69]: 
0    4
1    2
2    1
3    2
4    6
5    4
6    4
7    6
8    4
9    4
dtype: int64
# 统计每个值出现的次数
s.value_counts()
Out[70]: 
4    5
6    2
2    2
1    1
dtype: int64

字符串方法

s = pd.Series(['A', 'B', 'C', 'Aaba', 'Baca', np.nan, 'CABA', 'dog', 'cat'])
s.str.lower()

合并

# 相当于sql语句中的union all
df = pd.DataFrame(np.random.randn(10, 4))
 df
Out[74]: 
          0         1         2         3
0 -0.548702  1.467327 -1.015962 -0.483075
1  1.637550 -1.217659 -0.291519 -1.745505
2 -0.263952  0.991460 -0.919069  0.266046
3 -0.709661  1.669052  1.037882 -1.705775
4 -0.919854 -0.042379  1.247642 -0.009920
5  0.290213  0.495767  0.362949  1.548106
6 -1.131345 -0.089329  0.337863 -0.945867
7 -0.932132  1.956030  0.017587 -0.016692
8 -0.575247  0.254161 -1.143704  0.215897
9  1.193555 -0.077118 -0.408530 -0.862495
# 先拆开,再用concat合起来
pieces = [df[:3], df[3:7], df[7:]]
pd.concat(pieces)
Out[76]: 
          0         1         2         3
0 -0.548702  1.467327 -1.015962 -0.483075
1  1.637550 -1.217659 -0.291519 -1.745505
2 -0.263952  0.991460 -0.919069  0.266046
3 -0.709661  1.669052  1.037882 -1.705775
4 -0.919854 -0.042379  1.247642 -0.009920
5  0.290213  0.495767  0.362949  1.548106
6 -1.131345 -0.089329  0.337863 -0.945867
7 -0.932132  1.956030  0.017587 -0.016692
8 -0.575247  0.254161 -1.143704  0.215897
9  1.193555 -0.077118 -0.408530 -0.862495

关联

left = pd.DataFrame({'key': ['foo', 'foo'], 'lval': [1, 2]})
right = pd.DataFrame({'key': ['foo', 'foo'], 'rval': [4, 5]})
left
Out[79]: 
   key  lval
0  foo     1
1  foo     2
#
right
Out[80]: 
   key  rval
0  foo     4
1  foo     5
# 下面以列名key去关联
pd.merge(left, right, on='key')
Out[81]: 
   key  lval  rval
0  foo     1     4
1  foo     1     5
2  foo     2     4
3  foo     2     5
#
left = pd.DataFrame({'key': ['foo', 'bar'], 'lval': [1, 2]})
right = pd.DataFrame({'key': ['foo', 'bar'], 'rval': [4, 5]})
#
left
Out[84]: 
   key  lval
0  foo     1
1  bar     2
#
right
Out[85]: 
   key  rval
0  foo     4
1  bar     5
# 主要和上面的那个例子作对比,这个例子主要说明默认连接是:内连接
In [86]: pd.merge(left, right, on='key')
Out[86]: 
   key  lval  rval
0  foo     1     4
1  bar     2     5

append


df = pd.DataFrame(np.random.randn(8, 4), columns=['A','B','C','D'])
df
Out[88]: 
          A         B         C         D
0  1.346061  1.511763  1.627081 -0.990582
1 -0.441652  1.211526  0.268520  0.024580
2 -1.577585  0.396823 -0.105381 -0.532532
3  1.453749  1.208843 -0.080952 -0.264610
4 -0.727965 -0.589346  0.339969 -0.693205
5 -0.339355  0.593616  0.884345  1.591431
6  0.141809  0.220390  0.435589  0.192451
7 -0.096701  0.803351  1.715071 -0.708758
# 获取第三行
s = df.iloc[3]
# 把s添加在df中,牛逼的pandas!
df.append(s, ignore_index=True)
Out[90]: 
          A         B         C         D
0  1.346061  1.511763  1.627081 -0.990582
1 -0.441652  1.211526  0.268520  0.024580
2 -1.577585  0.396823 -0.105381 -0.532532
3  1.453749  1.208843 -0.080952 -0.264610
4 -0.727965 -0.589346  0.339969 -0.693205
5 -0.339355  0.593616  0.884345  1.591431
6  0.141809  0.220390  0.435589  0.192451
7 -0.096701  0.803351  1.715071 -0.708758
8  1.453749  1.208843 -0.080952 -0.264610

分组

df = pd.DataFrame({'A' : ['foo', 'bar', 'foo', 'bar',
                                       'foo', 'bar', 'foo', 'foo'],
                                'B' : ['one', 'one', 'two', 'three',
                                       'two', 'two', 'one', 'three'],
                                'C' : np.random.randn(8),
                                'D' : np.random.randn(8)}) 
# 以列A去分组,然后分组后求和,看出默认忽略了B列,因为B列是字符串类型,sum函数不支持
df.groupby('A').sum()
Out[93]: 
            C        D
A                     
bar -2.802588  2.42611
foo  3.146492 -0.63958
# 同样可以
df.groupby(['A','B']).sum()

下面的图纠正一处错误,利用stack函数,是把列名作为DataFrame的索引,也就多加了一内层索引,不是截图说的作为某一列的值。

stack用法

unstack用法

透视表
pivot_table用法

时间序列,这里不做详解
时间序列

类别数据类型

df = pd.DataFrame({"id":[1,2,3,4,5,6], "raw_grade":['a', 'b', 'b', 'a', 'a', 'e']})
# 数据类型转变为category数据类型,并赋值给grade列,相当于有3列名
# id,raw_grade,grade
df["grade"] = df["raw_grade"].astype("category")
df["grade"]
Out[129]: 
0    a
1    b
2    b
3    a
4    a
5    e
Name: grade, dtype: category
Categories (3, object): [a, b, e]
# 更改之前的category数据,用Series.cat.categories函数,之前是Categories (3, object): [a, b, e],更改后变为["very good", "good", "very bad"],一一对应
df["grade"].cat.categories = ["very good", "good", "very bad"]

# 利用set_categories设置类别有哪些,比如原来是 ["very good", "good", "very bad"],也就3个类别,现在变为["very bad", "bad", "medium", "good", "very good"],共5个类别。
df["grade"] = df["grade"].cat.set_categories(["very bad", "bad", "medium", "good", "very good"])
#
df["grade"]
Out[132]: 
0    very good
1         good
2         good
3    very good
4    very good
5     very bad
Name: grade, dtype: category
Categories (5, object): [very bad, bad, medium, good, very good]
df["grade"]
Out[132]: 
0    very good
1         good
2         good
3    very good
4    very good
5     very bad
Name: grade, dtype: category
Categories (5, object): [very bad, bad, medium, good, very good]
# 根据值排序
df.sort_values(by="grade")
Out[133]: 
   id raw_grade      grade
5   6         e   very bad
1   2         b       good
2   3         b       good
0   1         a  very good
3   4         a  very good
4   5         a  very good

画图

plot1

plot2

读写数据,csv,hdf5,Excel,数据库等

# 写入数据csv
df.to_csv('foo.csv')
# 读取数据csv
pd.read_csv('foo.csv')
# 写、读hdf5数据
df.to_hdf('foo.h5','df')
pd.read_hdf('foo.h5','df')
# 读写Excel
df.to_excel('foo.xlsx', sheet_name='Sheet1')
pd.read_excel('foo.xlsx', 'Sheet1', index_col=None, na_values=['NA'])


©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,496评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,407评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,632评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,180评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,198评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,165评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,052评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,910评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,324评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,542评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,711评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,424评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,017评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,668评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,823评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,722评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,611评论 2 353

推荐阅读更多精彩内容