数据科学包-Day2-pandas(三)

重新索引

import pandas as pd
import numpy as np

Series

s = pd.Series([1, 3, 5, 6, 8], index=list('acefh'))
s
s.reindex(list('abcdefgh'))
s.reindex(list('abcdefgh'), fill_value=0)
#method='bfill'
s.reindex(list('abcdefgh'), method='ffill')

DataFrame

df = pd.DataFrame(np.random.randn(4, 6), index=list('ADFH'), columns=['one', 'two', 'three', 'four', 'five', 'six'])
df
df2 = df.reindex(index=list('ABCDEFGH'))
df2
df.loc['A']['one'] = 100
df
df.reindex(columns=['one', 'three', 'five', 'seven'])
df.reindex(columns=['one', 'three', 'five', 'seven'], fill_value=0)
# fill method 只对行有效
df.reindex(columns=['one', 'three', 'five', 'seven'], method='ffill')
df.reindex(index=list('ABCDEFGH'), method='ffill')

丢弃部分数据

df = pd.DataFrame(np.random.randn(4, 6), index=list('ABCD'), columns=['one', 'two', 'three', 'four', 'five', 'six'])
df
df.drop('A')
df2 = df.drop(['two', 'four'], axis=1)
df2
# 数据拷贝
df.iloc[0, 0] = 100
df

广播运算

df = pd.DataFrame(np.arange(12).reshape(4, 3), index=['one', 'two', 'three', 'four'], columns=list('ABC'))
df
df.loc['one']
df - df.loc['one']

函数应用
apply: 将数据按行或列进行计算
applymap: 将数据按元素为进行计算

df = pd.DataFrame(np.arange(12).reshape(4, 3), index=['one', 'two', 'three', 'four'], columns=list('ABC'))
df
# 每一列作为一个 Series 作为参数传递给 lambda 函数
df.apply(lambda x: x.max() - x.min())
# 每一行作为一个 Series 作为参数传递给 lambda 函数
df.apply(lambda x: x.max() - x.min(), axis=1)
# 返回多个值组成的 Series
def min_max(x):
    return pd.Series([x.min(), x.max()], index=['min', 'max'])
df.apply(min_max, axis=1)
# applymap: 逐元素运算
df = pd.DataFrame(np.random.randn(4, 3), index=['one', 'two', 'three', 'four'], columns=list('ABC'))
df
formater = '{0:.02f}'.format
# formater = lambda x: '%.02f' % x
df.applymap(formater)

排序和排名

df = pd.DataFrame(np.random.randint(1, 10, (4, 3)), index=list('ABCD'), columns=['one', 'two', 'three'])
df
df.sort_values(by='one')
s = pd.Series([3, 6, 2, 6, 4])
s.rank()
s.rank(method='first', ascending=False)

数据唯一性及成员资格
适用于 Series

s = pd.Series(list('abbcdabacad'))
s
s.unique()
s.value_counts()
s.isin(['a', 'b', 'c'])

索引
行索引
列索引
索引的分类
重复索引的处理

s = pd.Series(np.random.rand(5), index=list('abcde'))
s
s.index
s.index.name = 'alpha'
s
df = pd.DataFrame(np.random.randn(4, 3), columns=['one', 'two', 'three'])
df
df.index
df.columns

重复索引

s = pd.Series(np.arange(6), index=list('abcbda'))
s
s['a']
s['c']
s.index.is_unique
s.index.unique()
s.groupby(s.index).sum()

层次化索引
可以使数据在一个轴上有多个索引级别。即可以用二维的数据表达更高维度的数据,使数据组织方式更清晰。它使用 pd.MultiIndex 类来表示。

层次化索引有什么作用?
比如我们在分析股票数据,我们的一级行索引可以是日期;二级行索引可以是股票代码,列索引可以是股票的交易量,开盘价,收盘价等等。这样我们就可以把多个股票放在同一个时间维度下进行考察和分析。

Series 多层索引

a = [['a', 'a', 'a', 'b', 'b', 'c', 'c'], [1, 2, 3, 1, 2, 2, 3]]
tuples = list(zip(*a))
tuples
index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second'])
index
s = pd.Series(np.random.randn(7), index=index)
s
s.index
s.index.levels[0]
s.index.levels[1]
s['b']
s['b':'c']
s[['b', 'a']]
s['b', 1]
s[:, 2]

DataFrame 多层索引

df = pd.DataFrame(np.random.randint(1, 10, (4, 3)), 
                  index=[['a', 'a', 'b', 'b'], [1, 2, 1, 2]], 
                  columns=[['one', 'one', 'two'], ['blue', 'red', 'blue']])
df.index.names = ['row-1', 'row-2']
df.columns.names = ['col-1', 'col-2']
df
df.loc['a']
type(df.loc['a'])
df.loc['a', 1]
df.loc['a', 1].index

索引交换及排序

df
df2 = df.swaplevel('row-1', 'row-2')
df2
df2.sortlevel(0)

按照索引级别进行统计

df
df.sum(level=0)
df.sum(level=1)
df2.sum(level=0)

索引与列的转换

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
df.set_index('c')
df2 = df.set_index(['c', 'd'])
df2
df3 = df2.reset_index().sort_index('columns')
df3
(df3 == df)
pd.IndexSlice

分组计算

import pandas as pd
import numpy as np

分组计算
分组计算三步曲:拆分 -> 应用 -> 合并

拆分:根据什么进行分组?
应用:每个分组进行什么样的计算?
合并:把每个分组的计算结果合并起来。

df = pd.DataFrame({'key1': ['a', 'a', 'b', 'b', 'a'],
                  'key2': ['one', 'two', 'one', 'two', 'one'],
                  'data1': np.random.randint(1, 10, 5),
                  'data2': np.random.randint(1, 10, 5)})
df

对 Series 进行分组
通过索引对齐关联起来

grouped = df['data1'].groupby(df['key1'])
grouped.mean()
df['data1'].groupby([df['key1'], df['key2']]).mean()

对 DataFrame 进行分组

df.groupby('key1').mean()
means = df.groupby(['key1', 'key2']).mean()['data1']
means
means.unstack()
df.groupby(['key1', 'key2'])['data1'].mean()

每个分组的元素个数

df.groupby(['key1', 'key2']).size()

对分组进行迭代

for name, group in df.groupby('key1'):
    print name
    print group
for name, group in df.groupby(['key1', 'key2']):
print name
print group
 

转化为字典

d = dict(list(df.groupby('key1')))
d
d['a']

按列分组

df.dtypes
grouped = df.groupby(df.dtypes, axis=1)
dict(list(grouped))
df = pd.DataFrame(np.random.randint(1, 10, (5, 5)), 
                  columns=['a', 'b', 'c', 'd', 'e'], 
                  index=['Alice', 'Bob', 'Candy', 'Dark', 'Emily'])
df
df.ix[1, 1:3] = np.NaN
df
mapping = {'a': 'red', 'b': 'red', 'c': 'blue', 'd': 'orange', 'e': 'blue'}
grouped = df.groupby(mapping, axis=1)
grouped.sum()
grouped.count()
grouped.size()

通过函数来分组
当函数作为分组依据时,数据表里的每个索引(可以是行索引,也可以是列索引)都会调用一次函数,函数的返回值作为分组的索引,即相同的返回值分在同一组。

df = pd.DataFrame(np.random.randint(1, 10, (5, 5)), 
                  columns=['a', 'b', 'c', 'd', 'e'], 
                  index=['Alice', 'Bob', 'Candy', 'Dark', 'Emily'])
df
def _dummy_group(idx):
    print idx
    return idx
df.groupby(_dummy_group)
df.groupby(_dummy_group, axis=1)
grouped = df.groupby(len)
grouped.sum()
grouped.size()
grouped.count()

多级索引数据根据索引级别来分组

columns = pd.MultiIndex.from_arrays([['China', 'USA', 'China', 'USA', 'China'],
                                     ['A', 'A', 'B', 'C', 'B']], names=['country', 'index'])
df = pd.DataFrame(np.random.randint(1, 10, (5, 5)), columns=columns)
df
df.groupby(level='country', axis=1).count()
df.groupby(level='country', axis=1).sum()
df.groupby(level='index', axis=1).count()

数据聚合
分组运算,先根据一定规则拆分后的数据,然后对数据进行聚合运算,如前面见到的 mean(), sum() 等就是聚合的例子。聚合时,拆分后的第一个索引指定的数据都会依次传给聚合函数进行运算。最后再把运算结果合并起来,生成最终结果。

聚合函数除了内置的 sum(), min(), max(), mean() 等等之外,还可以自定义聚合函数。自定义聚合函数时,使用 agg() 或 aggregate() 函数。

内置聚合函数

df = pd.DataFrame({'key1': ['a', 'a', 'b', 'b', 'a'],
                  'key2': ['one', 'two', 'one', 'two', 'one'],
                  'data1': np.random.randint(1, 10, 5),
                  'data2': np.random.randint(1, 10, 5)})
df
df['data1'].groupby(df['key1']).sum()

自定义聚合函数

def peak_verbose(s):
    print type(s)
    return s.max() - s.min()
grouped = df.groupby('key1')
grouped.agg(peak_verbose)

应用多个聚合函数

grouped['data1', 'data2'].agg(['mean', 'std', peak])
# 给聚合后的列取名
grouped['data1'].agg([('agerage', 'mean'), ('max-range', peak)])

给不同的列应用不同的聚合函数
使用 dict 作为参数来实现

d = {'data1': ['mean', peak, 'max', 'min'],
     'data2': 'sum'}
grouped.agg(d)

重置索引

grouped.agg(d).reset_index()
df.groupby('key1', as_index=False).agg(d)

分组运算和转换
groupby 是特殊的分组运算。更一般的分组运算包括 “拆分 - 应用 - 合并”。这里介绍 transform() 和 apply() 来实现分组运算。
transform

df = pd.DataFrame({'key1': ['a', 'a', 'b', 'b', 'a'],
                  'key2': ['one', 'two', 'one', 'two', 'one'],
                  'data1': np.random.randint(1, 10, 5),
                  'data2': np.random.randint(1, 10, 5)})
df
# 给 df 每行都添加一个以 key1 分组后的平均值
k1_mean = df.groupby('key1').mean().add_prefix('mean_')
k1_mean
pd.merge(df, k1_mean, left_on='key1', right_index=True)
# 使用 transform 简化处理
k1_mean = df.groupby('key1').transform(np.mean).add_prefix('mean_')
k1_mean
df[k1_mean.columns] = k1_mean
df

距平化
与平均值的差异值

df = pd.DataFrame(np.random.randint(1, 10, (5, 5)), 
                  columns=['a', 'b', 'c', 'd', 'e'], 
                  index=['Alice', 'Bob', 'Candy', 'Dark', 'Emily'])
df
def demean(s):
    return s - s.mean()

key = ['one', 'one', 'two', 'one', 'two']
demeaned = df.groupby(key).transform(demean)
demeaned
demeaned.groupby(key).mean()

apply 函数
我们介绍过 DataFrame 的 apply 函数是逐行或逐列来处理数据。GroupBy 的 apply 函数对每个分组进行计算。

df = pd.DataFrame({'key1': ['a', 'a', 'b', 'b', 'a', 'a', 'a', 'b', 'b', 'a'],
                  'key2': ['one', 'two', 'one', 'two', 'one', 'one', 'two', 'one', 'two', 'one'],
                  'data1': np.random.randint(1, 10, 10),
                  'data2': np.random.randint(1, 10, 10)})
df
# 根据 column 排序,输出其最大的 n 行数据
def top(df, n=2, column='data1'):
    return df.sort_values(by=column, ascending=False)[:n]

top(df, n=5)
df.groupby('key1').apply(top)
# 传递参数
df.groupby('key1').apply(top, n=3, column='data2')
# 禁用分组键
df.groupby('key1', group_keys=False).apply(top)

apply 应用示例:用不同的分组平均值填充空缺数据

states = ['Ohio', 'New York', 'Vermont', 'Florida',
          'Oregon', 'Nevada', 'California', 'Idaho']
group_key = ['East'] * 4 + ['West'] * 4
data = pd.Series(np.random.randn(8), index=states)
data[['Vermont', 'Nevada', 'Idaho']] = np.nan
data
data.groupby(group_key).mean()
fill_mean = lambda g: g.fillna(g.mean())

data.groupby(group_key).apply(fill_mean)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值