master
/ 3Pandas 基础.ipynb

3Pandas 基础.ipynb @96fc089view markup · raw · history · blame

Notebook

Pandas 基础

在这节课中,我们将会学习到 Pandas 的相关内容。

Pandas 基于 NumPy 创建,并纳入了大量库及一些标准的数据模型,
提供了大量能使我们快速便捷地处理数据的函数与方法,可以高效的操作大型数据集。

In [ ]:
%matplotlib inline

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

产生 Pandas 对象

pandas 中有三种基本结构:

  • Series
    • 1D labeled homogeneously-typed array
  • DataFrame
    • General 2D labeled, size-mutable tabular structure with potentially heterogeneously-typed columns
  • Panel
    • General 3D labeled, also size-mutable array

Series

一维 Series 可以用一维列表初始化:

In [ ]:
s = pd.Series([1,3,5,np.nan,6,8])
print(s)

默认情况下,Series 的下标都是数字(可以使用额外参数指定),类型是统一的。

DataFrame

DataFrame 则是个二维结构,这里首先构造一组时间序列,作为我们第一维的下标:

In [ ]:
dates = pd.date_range('20130101', periods=6)
print(dates)

然后创建一个 DataFrame 结构:

In [ ]:
df = pd.DataFrame(np.random.randn(6,4), index=dates, columns=list('ABCD'))

df

默认情况下,如果不指定 index 参数和 columns,那么他们的值将用从 0 开始的数字替代。

除了向 DataFrame 中传入二维数组,我们也可以使用字典传入数据:

In [ ]:
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

字典的每个 key 代表一列,其 value 可以是各种能够转化为 Series 的对象。

Series 要求所有的类型都一致不同,DataFrame 值要求每一列数据的格式相同:

In [ ]:
df2.dtypes

查看数据

头尾数据

headtail 方法可以分别查看最前面几行和最后面几行的数据(默认为 5):

In [ ]:
df.head()

最后 3 行:

In [ ]:
df.tail(3)

编程练习

要求:查看df 的前 2 行数据。

In [ ]:
# 请编写你的答案
In [ ]:
df.head(2)

下标,列标,数据

下标使用 index 属性查看:

In [ ]:
df.index

列标使用 columns 属性查看:

In [ ]:
df.columns

数据值使用 values 查看:

In [ ]:
df.values

统计数据

查看简单的统计数据:

In [ ]:
df.describe()

转置

In [ ]:
df.T

排序

sort_index(axis=0, ascending=True) 方法按照下标大小进行排序,axis=0 表示按第 0 维进行排序。

In [ ]:
df.sort_index(ascending=False)
In [ ]:
df.sort_index(axis=1, ascending=False)

sort_values(by, axis=0, ascending=True) 方法按照 by 的值的大小进行排序,例如按照 B 列的大小:

In [ ]:
df.sort_values(by="B")

编程练习

要求:将 df 的按 A 列由大到小排序。

In [ ]:
# 请编写你的答案
In [ ]:
df.sort_values(by='A', ascending=False)

索引

虽然 DataFrame 支持 Python/Numpy 的索引语法,但是推荐使用 .at, .iat, .loc, .iloc 和 .ix 方法进行索引。

读取数据

选择单列数据:

In [ ]:
df["A"]

也可以用 df.A

In [ ]:
df.A

使用切片读取多行:

In [ ]:
df[0:3]

index 名字也可以进行切片:

In [ ]:
df["20130101":"20130103"]

使用 label 索引

loc 可以方便的使用 label 进行索引:

In [ ]:
df.loc[dates[0]]

多列数据:

In [ ]:
df.loc[:,['A','B']]

选择多行多列:

In [ ]:
df.loc['20130102':'20130104',['A','B']]

数据降维:

In [ ]:
df.loc['20130102',['A','B']]

得到标量值:

In [ ]:
df.loc[dates[0],'B']

不过得到标量值可以用 at,速度更快:

In [ ]:
%timeit -n100 df.loc[dates[0],'B']
%timeit -n100 df.at[dates[0],'B']

print(df.at[dates[0],'B'])

使用位置索引

iloc 使用位置进行索引:

In [ ]:
df.iloc[3]

连续切片:

In [ ]:
df.iloc[3:5,0:2]

索引不连续的部分:

In [ ]:
df.iloc[[1,2,4],[0,2]]

索引整行:

In [ ]:
df.iloc[1:3,:]

整列:

In [ ]:
df.iloc[:, 1:3]

标量值:

In [ ]:
df.iloc[1,1]

当然,使用 iat 索引标量值更快:

In [ ]:
%timeit -n100 df.iloc[1,1]
%timeit -n100 df.iat[1,1]

df.iat[1,1]

布尔型索引

所有 A 列大于 0 的行:

In [ ]:
df[df.A > 0]

只留下所有大于 0 的数值:

In [ ]:
df[df > 0]

使用 isin 方法做 filter 过滤:

In [ ]:
df2 = df.copy()
df2['E'] = ['one', 'one','two','three','four','three']

df2
In [ ]:
df2[df2['E'].isin(['two','four'])]

编程练习

要求:删选 df A 列大于 -1 的数据,并只展示 B 列的数据。

In [ ]:
# 请编写你的答案
In [ ]:
df[df.A > -1].B

设定数据的值

In [ ]:
s1 = pd.Series([1,2,3,4,5,6], index=pd.date_range('20130102', periods=6))

s1

像字典一样,直接指定 F 列的值为 s1,此时以 df 已有的 index 为标准将二者进行合并,s1 中没有的 index 项设为 NaN,多余的项舍去:

In [ ]:
df['F'] = s1

df

或者使用 atiat 修改单个值:

In [ ]:
df.at[dates[0],'A'] = 0

df
In [ ]:
df.iat[0, 1] = 0

df

设定一整列:

In [ ]:
df.loc[:,'D'] = np.array([5] * len(df))

df

设定满足条件的数值:

In [ ]:
df2 = df.copy()

df2[df2 > 0] = -df2

df2

缺失数据

In [ ]:
df1 = df.reindex(index=dates[0:4], columns=list(df.columns) + ['E'])
df1.loc[dates[0]:dates[1],'E'] = 1

df1

丢弃所有缺失数据的行得到的新数据:

In [ ]:
df1.dropna(how='any')

填充缺失数据:

In [ ]:
df1.fillna(value=5)

检查缺失数据的位置:

In [ ]:
pd.isnull(df1)

计算操作

统计信息

每一列的均值:

In [ ]:
df.mean()

每一行的均值:

In [ ]:
df.mean(1)

多个对象之间的操作,如果维度不对,pandas 会自动调用 broadcasting 机制:

In [ ]:
s = pd.Series([1,3,5,np.nan,6,8], index=dates).shift(2)

s

相减 df - s

In [ ]:
df.sub(s, axis='index')

编程练习

要求:计算 df B 列的和。

In [ ]:
# 请编写你的答案
In [ ]:
df['B'].sum()

apply 操作

R 中的 apply 操作类似,接收一个函数,默认是对将函数作用到每一列上:

In [ ]:
df.apply(np.cumsum)

求每列最大最小值之差:

In [ ]:
df.apply(lambda x: x.max() - x.min())

直方图

In [ ]:
s = pd.Series(np.random.randint(0, 7, size=10))

s

直方图信息:

In [ ]:
s.value_counts()

绘制直方图信息:

In [ ]:
h = s.hist()

字符串方法

Series 或者 DataFrame 的某一列是字符串时,我们可以用 .str 对这个字符串数组进行字符串的基本操作:

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

s.str.lower()

合并

连接

In [ ]:
df = pd.DataFrame(np.random.randn(10, 4))
df

可以使用 pd.concat 函数将多个 pandas 对象进行连接:

In [ ]:
pieces = [df[:2], df[4:5], df[7:]]

pd.concat(pieces)

数据库中的 Join

merge 可以实现数据库中的 join 操作:

In [ ]:
left = pd.DataFrame({'key': ['foo', 'foo'], 'lval': [1, 2]})
right = pd.DataFrame({'key': ['foo', 'foo'], 'rval': [4, 5]})

print(left)
print(right)
In [ ]:
pd.merge(left, right, on='key')

append

DataFrame 中添加行:

In [ ]:
df = pd.DataFrame(np.random.randn(8, 4), columns=['A','B','C','D'])

df

将第三行的值添加到最后:

In [ ]:
s = df.iloc[3]

df.append(s, ignore_index=True)

Grouping

In [ ]:
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)})

df

按照 A 的值进行分类:

In [ ]:
df.groupby('A').sum()

按照 A, B 的值进行分类:

In [ ]:
df.groupby(['A', 'B']).sum()

改变形状

Stack

产生一个多 indexDataFrame

In [ ]:
tuples = list(zip(*[['bar', 'bar', 'baz', 'baz',
                     'foo', 'foo', 'qux', 'qux'],
                    ['one', 'two', 'one', 'two',
                     'one', 'two', 'one', 'two']]))

index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second'])
df = pd.DataFrame(np.random.randn(8, 2), index=index, columns=['A', 'B'])

df

stack 方法将 columns 变成一个新的 index 部分:

In [ ]:
df2 = df[:4]

stacked = df2.stack()

stacked

可以使用 unstack() 将最后一级 index 放回 column

In [ ]:
stacked.unstack()

也可以指定其他的级别:

In [ ]:
stacked.unstack(1)

时间序列

金融分析中常用到时间序列数据:

In [ ]:
rng = pd.date_range('3/6/2012 00:00', periods=5, freq='D')
ts = pd.Series(np.random.randn(len(rng)), rng)

ts

标准时间表示:

In [ ]:
ts_utc = ts.tz_localize('UTC')

ts_utc

改变时区表示:

In [ ]:
ts_utc.tz_convert('US/Eastern')

Categoricals

In [ ]:
df = pd.DataFrame({"id":[1,2,3,4,5,6], "raw_grade":['a', 'b', 'b', 'a', 'a', 'e']})

df

可以将 grade 变成类别:

In [ ]:
df["grade"] = df["raw_grade"].astype("category")

df["grade"]

将类别的表示转化为有意义的字符:

In [ ]:
df["grade"].cat.categories = ["very good", "good", "very bad"]

df["grade"]

添加缺失的类别:

In [ ]:
df["grade"] = df["grade"].cat.set_categories(["very bad", "bad", "medium", "good", "very good"])
df["grade"]

使用 grade 分组:

In [ ]:
df.groupby("grade").size()

绘图

使用 ggplot 风格:

In [ ]:
plt.style.use('ggplot')

Series 绘图:

In [ ]:
ts = pd.Series(np.random.randn(1000), index=pd.date_range('1/1/2000', periods=1000))

p = ts.cumsum().plot()

DataFrame 按照 columns 绘图:

In [ ]:
df = pd.DataFrame(np.random.randn(1000, 4), index=ts.index,
                  columns=['A', 'B', 'C', 'D'])

df.cumsum().plot()
p = plt.legend(loc="best")

文件读写

csv

写入文件:

In [ ]:
df.to_csv('foo.csv')

从文件中读取:

In [ ]:
pd.read_csv('foo.csv').head()

excel

写入文件:

In [ ]:
df.to_excel('foo.xlsx', sheet_name='Sheet1')

读取文件:

In [ ]:
pd.read_excel('foo.xlsx', 'Sheet1', index_col=None, na_values=['NA']).head()

清理生成的临时文件:

In [ ]:
import glob
import os

for f in glob.glob("foo*"):
    os.remove(f)

编程练习

In [ ]:
import numpy as np
import pandas as pd
data = {'animal': ['cat', 'cat', 'snake', 'dog', 'dog', 'cat', 'snake', 'cat', 'dog', 'dog'],
        'age': [2.5, 5, 0.5, np.nan, 5, 2, 4.5, np.nan, 5, 3],
        'visits': [1, 4, 2, 3, 2, 3, 1, 2, 2, 1],
        'priority': ['yes', 'yes', 'no', 'yes', 'no', 'no', 'no', 'yes', 'no', 'no']}

labels = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
df_test = pd.DataFrame(data, index=labels)
df_test
  1. 要求: 取出 age 值大于3的行
In [ ]:
# 请编写你的答案
In [ ]:
df_test[df_test['age'] > 3]
  1. 要求: 使用 iloc 方法展示前三行
In [ ]:
# 请编写你的答案
In [ ]:
df_test.iloc[:3]
  1. 要求: 计算 visits 的总和。
In [ ]:
# 请编写你的答案
In [ ]:
df_test['visits'].sum()