快乐学习
前程无忧、中华英才非你莫属!

Pandas入门

之前由于为了使用,简单的学习下Pandas,而后发现它是个强大的家伙~,因为python版本进行了更新,随之有些api有所改动,所以重新整理官网入门级demo教程来加深印象~
Pandas易于使用的数据结构和数据分析工具。中文称呼为:熊猫!
这是关于pandas的简短介绍,主要面向新用户。可以参阅Cookbook了解更复杂的使用方法。习惯上,我们做以下导入
import pandas as pd
import numpy as np
import matplotlib.pyplot as pl

创建一个Series通过传递值的列表,让大熊猫创建一个默认的整数索引:
s = pd.Series([1,3,5,np.nan,6,8])
s

创建一个DataFramenumpy数组,带有日期时间索引和标签列:
dates = pd.date_range('20130101', periods=6)
dates
df = pd.DataFrame(np.random.randn(6,4), index=dates, columns=list('ABCD'))
df

DataFrame通过传递一个字典,可以转换为一序列对象
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

明确所有类型
df2.dtype

# 查看框架的顶部和底部的行
df.head()#全部内容
df.tail(3)#底部三行

#显示索引,列和底层numpy数据
df.index #显示索引kye
df.columns# 显示列值*(A,B,C,D)
df.values #只显示值

# 描述显示您的数据的快速统计摘要
df.describe()

#转置您的数据

df.T #x-y颠倒

# 按轴排序
df.sort_index(axis=1, ascending=False)

# 按值排序
df.sort_values(by='B')

注释: 标准Python / Numpy表达式可以完成这些互动工作, 但在生产代码中, 我们推荐使用优化的pandas数据访问方法, .at, .iat, .loc, .iloc .ix.
# 读取
# 选择单列, 这会产生一个序列, 等价df.A
df['A']
# 选择通过[],切行片
df[0:3]  #取前面三行
df['20130102':'20130104'] #取包含2013-01-02 到2013-01-04和之间的数据
# 使用标签获取横截面
df.loc[dates[0]]  # dates 索引为零的行数据
# 使用标签选择多轴
df.loc[:,['A','B']] #取a到b两列纵行
# 显示标签切片, 包含两个端点
df.loc['20130102':'20130104',['A','B']] #显示20130102到20130104行数,然后a-b的纵行。
# 降低返回对象维度
df.loc['20130102',['A','B']]
# 获取标量值
df.loc[dates[0],'A']   #获取dates索引为零的的行行以及A列交叉的值。
# 按位置选择更多内容
df.iloc[3]  #取出y轴索引为3的值,x轴数据,
df.iloc[3:5,0:2]   #y轴,x轴范围过滤,索引3到索引5(不包括索引5),x轴(0-2)不包括2  通过整数片,类似于numpy / python
df.iloc[[1,2,4],[0,2]]  #整数位置的位置列表,类似于numpy / python风格
#用于明确地切割行
df.iloc[1:3,:]  # 输出y轴索引1到索引2,不包括索引3,然后x轴全部的值。
df.iloc[:,1:3]  # 输出x轴索引1-2的值,y轴全部,用于明确地切分列
# 为了明确地获取一个值
df.iloc[1,1]
# 为了快速访问标量(等同于之前的方法)
df.iat[1,1]
# 使用单个列的值来选择数据。
df[df.A > 0]
# 从满足布尔条件的DataFrame中选择值
df[ df > 0 ]
# 使用isin()过滤方法
df2 = df.copy()
df2['E'] = ['one', 'one','two','three','four','three']
df2
df2[df2['E'].isin(['two','four'])]
#设置新列自动按索引排列数据
s1 = pd.Series([1,2,3,4,5,6], index=pd.date_range('20130102', periods=6))
s1
df.at[dates[0], 'A'] = 0  # 通过标签设置值
df.iat[0, 1] = 0  #按位置设置值
df.loc[:,'D'] = np.array([5] * len(df))  #通过分配一个numpy数组进行设置
df
# 条件设置操作。
df2 = df.copy()
df2[df2 > 0] = -df2
df2
# 熊猫主要使用这个值np.nan来表示缺失的数据
# Reindexing允许您更改/添加/删除指定轴上的索引。这将返回数据的副本。
df1 = df.reindex(index=dates[0:4], columns=list(df.columns) + ['E'])   #添加E列,因为没赋值都是NaN!
df1
df1.loc[dates[0]:dates[1],'E'] = 1  # 在E列上y轴索引0,1设置值为1.
df1
# 删除任何缺少数据的行
df1.dropna(how='any')
# 填写缺少的数据
df1.fillna(value=6)   #把NaN,无效的值,用6代替。
# 获取值是否nan的布尔标记
pd.isnull(df1)
# 运算一般操作不包括丢失的数据。
df.mean()  #执行描述性统计
df.mean(1)#相同的操作在另一个轴上
# 用于运算的对象有不同的维度并需要对齐.除此之外,pandas会自动沿着指定维度计算.
s = pd.Series([1,3,5,np.nan,6,8],index=dates).shift(2)  #索引保持不动,值被下移动两位
s
df
df.sub(s,axis='index')
# 在数据上使用函数
df.apply(np.cumsum)
df.apply(lambda x: x.max() - x.min())
# 直方图
s = pd.Series(np.random.randint(0, 7, size=10))
s
s.value_counts()
# 字符串方法
# 序列可以使用一些字符串处理方法很轻易操作数据组中的每个元素,比如以下代码片断。 注意字符匹配方法默认情况下通常使用正则表达式(并且大多数时候都如此). 更多信息请参阅字符串向量方法.
s = pd.Series(['A', 'B', 'C', 'Aaba', 'Baca', np.nan, 'CABA', 'dog', 'cat'])
s.str.lower()
# pandas提供各种工具以简便合并序列,数据桢,和组合对象, 在连接/合并类型操作中使用多种类型索引和相关数学函数.
df = pd.DataFrame(np.random.randn(10, 4))
df
pieces = [df[:3], df[3:7], df[7:]]
pd.concat(pieces)
# SQL样式合并、
left = pd.DataFrame({'key': ['foo', 'foo'], 'lval': [1, 2]})
right = pd.DataFrame({'key': ['foo', 'foo'], 'rval': [4, 5]})
left
right
pd.merge(left, right, on='key')
# 添加行到数据
df = pd.DataFrame(np.random.randn(8, 4), columns=['A','B','C','D'])
df
s = df.iloc[3]
df.append(s, ignore_index=True)
# 分组将数据按某些标准分割为不同的,在每个独立组上应用函数组合结果为一个数据结构
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
# 分组然后应用函数统计总和存放到结果组
df.groupby('A').sum()
# 按多列分组为层次索引,然后应用函数
df.groupby(['A','B']).sum()
# 堆叠
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'])
df2 = df[:4]
df2
# 堆叠 函数 “压缩” 数据桢的列一个级别.
stacked = df2.stack()
stacked
# 被“堆叠”数据桢或序列(有多个索引作为索引), 其堆叠的反向操作是未堆栈, 上面的数据默认反堆叠到上一级别:
stacked.unstack()
stacked.unstack(1)
stacked.unstack(0)
# 数据透视表
df = pd.DataFrame({'A' : ['one', 'one', 'two', 'three'] * 3,
                   'B' : ['A', 'B', 'C'] * 4,
                   'C' : ['foo', 'foo', 'foo', 'bar', 'bar', 'bar'] * 2,
                   'D' : np.random.randn(12),
                   'E' : np.random.randn(12)})
df
#x轴列字段为C,y轴索引为,AB,值为D字段
pd.pivot_table(df, values='D', index=['A', 'B'], columns=['C'])
# 时间序列,pandas有易用,强大且高效的函数用于高频数据重采样转换操作
rng = pd.date_range('1/1/2012', periods=100, freq='S')
ts = pd.Series(np.random.randint(0, 500, len(rng)), index=rng)
ts.resample('5Min', how='sum')
# 时区表示
rng = pd.date_range('3/6/2012 00:00', periods=5, freq='D')
ts = pd.Series(np.random.randn(len(rng)), rng)
ts
ts_utc = ts.tz_localize('UTC')
ts_utc
# 转换到其它时区
ts_utc.tz_convert('US/Eastern')
# 转换不同的时间跨度
rng = pd.date_range('1/1/2012', periods=5, freq='M')
ts = pd.Series(np.random.randn(len(rng)), index=rng)
ts
ps = ts.to_period()
ps
ps.to_timestamp()
# 转换时段并且使用一些运算函数, 下例中, 我们转换年报11月到季度结束每日上午9点数据
prng = pd.period_range('1990Q1', '2000Q4', freq='Q-NOV')
ts = pd.Series(np.random.randn(len(prng)), prng)
ts.index = (prng.asfreq('M', 'e') + 1).asfreq('H', 's') + 9
ts.head()
# 分类
# 自版本0.15起,   pandas可以在数据桢中包含分类
df = pd.DataFrame({"id":[1,2,3,4,5,6], "raw_grade":['a', 'b', 'b', 'a', 'a', 'e']})
# 转换原始类别为分类数据类型.
df["grade"] = df["raw_grade"].astype("category")
df["grade"]
# 重命令分类为更有意义的名称 (分配到Series.cat.categories对应位置!)
df["grade"].cat.categories = ["very good", "good", "very bad"]
# 重排顺分类,同时添加缺少的分类(序列 .cat方法下返回新默认序列)
df["grade"] = df["grade"].cat.set_categories(["very bad", "bad", "medium", "good", "very good"])
df["grade"]
# 类别列分组,并且也显示空类别
df.groupby("grade").size()
# 绘图
ts = pd.Series(np.random.randn(1000), index=pd.date_range('1/1/2000', periods=1000))
ts = ts.cumsum()
ts.plot()
# 在数据桢中,可以很方便的绘制带标签列:
df = pd.DataFrame(np.random.randn(1000, 4), index=ts.index,columns=['A', 'B', 'C', 'D'])
df = df.cumsum()
plt.figure(); df.plot(); plt.legend(loc='best')
# 写入csv文件
df.to_csv('foo.csv')
# 读取csv文件
pd.read_csv('foo.csv')
# 写入HDF5存储
df.to_hdf('foo.h5','df')
# 读取HDF5存储
pd.read_hdf('foo.h5','df')
# 写入excel文件
df.to_excel('foo.xlsx', sheet_name='Sheet1')
# 读取excel文件
pd.read_excel('foo.xlsx', 'Sheet1', index_col=None, na_values=['NA'])


pandas基础

流处理

流处理,听起来很高大上啊,其实就是分块读取。有这么一些情况,有一个很大的几个G的文件,没办法一次处理,那么就分批次处理,一次处理1百万行,接着处理下1百万行,慢慢地总是能处理完的。
# 使用类似迭代器的方式
data=pd.read_csv(file, chunksize=1000000)
for sub_df in data:
print('do something in sub_df here')

索引

Series和DataFrame都是有索引的,索引的好处是快速定位,在涉及到两个Series或DataFrame时可以根据索引自动对齐,比如日期自动对齐,这样可以省去很多事。

缺失值

pd.isnull(obj)
obj.isnull()

将字典转成数据框,并赋予列名,索引

DataFrame(data, columns=['col1','col2','col3'...],
index = ['i1','i2','i3'...])

查看列名

DataFrame.columns

查看索引

DataFrame.index

重建索引

obj.reindex(['a','b','c','d','e'...], fill_value=0]
#按给出的索引顺序重新排序,而不是替换索引。如果索引没有值,就用0填充
#就地修改索引
data.index=data.index.map(str.upper)

列顺序重排(也是重建索引)

DataFrame.reindex[columns=['col1','col2','col3'...])`
#也可以同时重建index和columns
DataFrame.reindex[index=['a','b','c'...],columns=['col1','col2','col3'...])

重建索引的快捷键

DataFrame.ix[['a','b','c'...],['col1','col2','col3'...]]

重命名轴索引

data.rename(index=str.title,columns=str.upper)
#修改某个索引和列名,可以通过传入字典
data.rename(index={'old_index':'new_index'},
columns={'old_col':'new_col'})

查看某一

DataFrame['state'] 或 DataFrame.state

查看某一行

需要用到索引
DataFrame.ix['index_name']

添加或删除一列

DataFrame['new_col_name'] = 'char_or_number'#删除行
DataFrame.drop(['index1','index2'...])
#删除列
DataFrame.drop(['col1','col2'...],axis=1)
#或del DataFrame['col1']

DataFrame选择子集

类型
说明
obj[val]
选择一列或多列
obj.ix[val]
选择一行或多行
obj.ix[:,val]
选择一列或多列
obj.ix[val1,val2]
同时选择行和列
reindx
对行和列重新索引
icol,irow
根据整数位置选取单列或单行
get_value,set_value
根据行标签和列标签选择单个值
针对series
obj[['a','b','c'...]]
obj['b':'e']=5

针对dataframe
#选择多列
dataframe[['col1','col2'...]]
#选择多行
dataframe[m:n]
#条件筛选
dataframe[dataframe['col3'>5]]
#选择子集
dataframe.ix[0:3,0:5]

dataframe和series的运算

会根据 index 和 columns 自动对齐然后进行运算,很方便啊
方法
说明
add
加法
sub
减法
div
除法
mul
乘法
#没有数据的地方用0填充空值
df1.add(df2,fill_value=0)
# dataframe 与 series 的运算
dataframe - series
规则是:
-------- -------- |
| | | | |
| | -------- |
| | |
| | v
--------
#指定轴方向
dataframe.sub(series,axis=0)
规则是:
-------- ---
| | | | ----->
| | | |
| | | |
| | | |
-------- ---

apply函数

f=lambda x:x.max()-x.min()
#默认对每一列应用
dataframe.apply(f)
#如果需要对每一行分组应用
dataframe.apply(f,axis=1)

排序和排名

#默认根据index排序,axis = 1 则根据columns排序
dataframe.sort_index(axis=0, ascending=False)
# 根据值排序
dataframe.sort_index(by=['col1','col2'...])
#排名,给出的是rank值
series.rank(ascending=False)
#如果出现重复值,则取平均秩次
#在行或列上面的排名
dataframe.rank(axis=0)

描述性统计

方法
说明
count
计数
describe
给出各列的常用统计量
min,max
最大最小值
argmin,argmax
最大最小值的索引位置(整数)
idxmin,idxmax
最大最小值的索引值
quantile
计算样本分位数
sum,mean
对列求和,均值
mediam
中位数
mad
根据平均值计算平均绝对离差
var,std
方差,标准差
skew
偏度(三阶矩)
Kurt
峰度(四阶矩)
cumsum
累积和
Cummins,cummax
累计组大致和累计最小值
cumprod
累计积
diff
一阶差分
pct_change
计算百分数变化

唯一值,值计数,成员资格

obj.unique()
obj.value_count()
obj.isin(['b','c'])

处理缺失值

# 过滤缺失值
# 只要有缺失值就丢弃这一行
dataframe.dropna()
#要求全部为缺失才丢弃这一行
dataframe.dropna(how='all')
# 根据列来判断
dataframe.dropna(how='all',axis=1)
# 填充缺失值
#1.用0填充
df.fillna(0)
#2.不同的列用不同的值填充
df.fillna({1:0.5, 3:-1})
#3.用均值填充
df.fillna(df.mean())
# 此时axis参数同前面,

将列转成行索引

df.set_index(['col1','col2'...])


数据清洗,重塑

合并数据集

# 取 df1,df2 都有的部分,丢弃没有的# 默认是inner的连接方式
pd.merge(df1,df2, how='inner')
#如果df1,df2的连接字段名不同,则需要特别指定
pd.merge(df1,df2,left_on='l_key',right_on='r_key')
#其他的连接方式有 left,right, outer等。
# 如果dataframe是多重索引,根据多个键进行合并
pd.merge(left, right, on=['key1','key2'],how = 'outer')
#合并后如果有重复的列名,需要添加后缀
pd.merge(left, right, on='key1', suffixes=('_left','_right'))

索引上的合并

#针对dataframe中的连接键不是列名,而是索引名的情况。
pd.merge(left, right, left_on = 'col_key', right_index=True)
#即左边的key是列名,右边的key是index。
#多重索引
pd.merge(left, right, left_on=['key1','key2'], right_index=True)

dataframe的join方法

#实现按索引合并。#其实这个join方法和数据库的join函数是以一样的理解
left.join(right, how='outer')
#一次合并多个数据框
left.join([right1,right2],how='outer')

轴向连接(更常用)

连接:concatenation 
绑定:binding 
堆叠:stacking

列上的连接

np.concatenation([df1,df2],axis=1) #np包
pd.concat([df1,df2], axis=1) #pd包
#和R语言中的 cbind 是一样的
#如果axis=0,则和 rbind 是一样的#索引对齐,没有的就为空
# join='inner' 得到交集
pd.concat([df1,df2], axis=1, join='innner')
# keys 参数,还没看明白
# ignore_index=True,如果只是简单的合并拼接而不考虑索引问题。
pd.concat([df1,df2],ignore_index=True)

合并重复数据

针对可能有索引全部或者部分重叠的两个数据集
填充因为合并时索引赵成的缺失值
where函数
#where即if-else函数
np.where(isnull(a),b,a)

combine_first方法
#如果a中值为空,就用b中的值填补
a[:-2].combine_first(b[2:])
#combine_first函数即对数据打补丁,用df2的数据填充df1中的缺失值
df1.combine_first(df2)

重塑层次化索引

stact:将数据转为长格式,即列旋转为行 
unstack:转为宽格式,即将行旋转为列

result=data.stack()
result.unstack()

长格式转为宽格式

pivoted = data.pivot('date','item','value')
#前两个参数分别是行和列的索引名,最后一个参数则是用来填充dataframe的数据列的列名。如果忽略最后一个参数,得到的dataframe会带有层次化的列。

透视表

table = df.pivot_table(values=["Price","Quantity"],
index=["Manager","Rep"],
aggfunc=[np.sum,np.mean],
margins=True))
#values:需要对哪些字段应用函数#index:透视表的行索引(row)#columns:透视表的列索引(column)#aggfunc:应用什么函数#fill_value:空值填充#margins:添加汇总项
#然后可以对透视表进行筛选
table.query('Manager == ["Debra Henley"]')
table.query('Status == ["pending","won"]')

移除重复数据

# 判断是否重复
data.duplicated()`
#移除重复数据
data.drop_duplicated()
#对指定列判断是否存在重复值,然后删除重复数据
data.drop_duplicated(['key1'])

交叉表

是一种用于计算分组频率的特殊透视表. 
注意,只对离散型的,分类型的,字符型的有用,连续型数据是不能计算频率这种东西的。

pd.crosstab(df.col1, df.col2, margins=True)

类似vlookup函数

利用函数或映射进行数据转换
#1.首先定义一个字典
meat_to_animal={
'bacon':'pig',
'pulled pork':'pig',
'honey ham':'cow'
}
#2.对某一列应用一个函数,或者字典,顺便根据这一列的结果创建新列
data['new_col']=data['food'].map(str.lower).map(meat_to_animal)

替换值

data.replace(-999,np.na)
#多个值的替换
data.replace([-999,-1000],np.na)
#对应替换
data.replace([-999,-1000],[np.na,0])
#对应替换也可以传入一个字典
data.replace({-999:np.na,-1000:0})

离散化

#定义分割点
bins=[20,40,60,80,100]
#切割
cats = pd.cut(series,bins)
#查看标签
cats.labels
#查看水平(因子)
cats.levels
#区间计数
pd.value_count(cats)
#自定义分区的标签
group_names=['youth','youngAdult','MiddleAge','Senior']
pd.cut(ages,bins,labels=group_names)

分位数分割
data=np.random.randn(1000)
pd.qcut(data,4) #四分位数
#自定义分位数,包含端点
pd.qcut(data,[0,0.3,0.5,0.9,1])

异常值

#查看各个统计量
data.describe()
#对某一列
col=data[3]
col[np.abs(col)>3]
#选出全部含有“超过3或-3的值的行
data[(np.abs(data)>3).any(1)]
#异常值替换
data[np.abs(data)>3]=np.sign(data)*3

抽样

#随机抽取k行
df.take(np.random.permutation(len(df))[:k])
#随机抽取k行,但是k可能大于df的行数#可以理解为过抽样了
df.take(np.random.randint(0,len(df),size=k))

数据摊平处理

相当于将类别属性转成因子类型,比如是否有车,这个字段有3个不同的值,有,没有,过段时间买,那么将会被编码成3个字段,有车,没车,过段时间买车,每个字段用0-1二值填充变成数值型。
#对摊平的数据列增加前缀
dummies = pd.get_dummies(df['key'],prefix='key')
#将摊平产生的数据列拼接回去
df[['data1']].join(dummies)

字符串操作

# 拆分
strings.split(',')
#根据正则表达式切分
re.split('s+',strings)
# 连接'a'+'b'+'c'...
或者
'+'.join(series)
# 判断是否存在's' in strings`
strings.find('s')
# 计数
strings.count(',')
# 替换
strings.replace('old','new')
# 去除空白字符
s.strip()

正则表达式

正则表达式需要先编译匹配模式,然后才去匹配查找,这样能节省大量的CPU时间。
re.complie:编译 
findall:匹配所有 
search:只返回第一个匹配项的起始和结束地址 
match:值匹配字符串的首部 
sub:匹配替换,如果找到就替换

#原始字符串
#编译匹配模式,IGNORECASE可以在使用的时候对大小写不敏感
pattern = r'[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}'
regex = re.compile(pattern,flags=re.IGNORECASE)
#匹配所有
regex.findall(strings)
#使用search
m = regex.search(strings) #获取匹配的地址
strings[m.start():m.end()]
#匹配替换
regex.sub('new_string', strings)

根据模式再切分

将模式切分,也就是将匹配到的进一步切分,通过pattern中的括号实现.
pattern = r'([A-Z0-9._%+-]+)@([A-Z0-9.-]+)\.([A-Z]{2,4})'
regex = re.compile(pattern)
regex.findall(strings)
#如果使用match
m=regex.match(string)
m.groups()
#效果是这样的
suzyu123@163.com --> [(suzyu123, 163, com)]
#获取 list-tuple 其中的某一列
matches.get(i)

分组聚合,计算

group_by技术

# 根据多个索引分组,然后计算均值
means = df['data1'].groupby([df['index1'],df['index2']).mean()
# 展开成透视表格式
means.unstack()

分组后价将片段做成一个字典

pieces = dict(list(df.groupby('index1')))
pieces['b']

groupby默认是对列(axis=0)分组,也可以在行(axis=1)上分组

语法糖,groupby的快捷函数

df.groupby('index1')['col_names']
df.groupby('index1')[['col_names']]
#是下面代码的语法糖
df['col_names'].groupby(df['index1'])
df.groupby(['index1','index2'])['col_names'].mean()

通过字典或series进行分组

people = DataFrame(np.random.randn(5, 5),
columns=['a', 'b', 'c', 'd', 'e'],
index=['Joe', 'Steve', 'Wes', 'Jim','Travis'])
# 选择部分设为na
people.ix[2:3,['b','c']]=np.na
mapping = {'a': 'red', 'b': 'red', 'c': 'blue',
'd': 'blue', 'e': 'red', 'f' : 'orange'}
people.groupby(mapping,axis=1).sum()

通过函数进行分组

#根据索引的长度进行分组
people.groupby(len).sum()

数据聚合

使用自定义函数

## 对所有的数据列使用自定义函数
df.groupby('index1').agg(myfunc)
#使用系统函数
df.groupby('index1')['data1']describe()

根据列分组应用多个函数

#分组
grouped = df.groupby(['col1','col2'])
#选择多列,对每一列应用多个函数
grouped['data1','data2'...].agg(['mean','std','myfunc'])

对不同列使用不同的函数

grouped = df.groupby(['col1','col2'])
#传入一个字典,对不同的列使用不同的函数#不同的列可以应用不同数量的函数
grouped.agg({'data1':['min','max','mean','std'],
'data2':'sum'})

分组计算后重命名列名

grouped = df.groupby(['col1','col2'])
grouped.agg({'data1':[('min','max','mean','std'),('d_min','d_max','d_mean','d_std')],
'data2':'sum'})

返回的聚合数据不要索引

df.groupby(['sex','smoker'], as_index=False).mean()

分组计算结果添加前缀

#对计算后的列名添加前缀
df.groupby('index1').mean().add_prefix('mean_')

将分组计算后的值替换到原数据框

#将函数应用到各分组,再将分组计算的结果代换原数据框的值#也可以使用自定义函数
df.groupby(['index1','index2'...]).transform(np.mean)

更一般化的apply函数

df.groupby(['col1','col2'...]).apply(myfunc)
df.groupby(['col1','col2'...]).apply(['min','max','mean','std'])

禁用分组键

分组键会跟原始对象的索引共同构成结果对象中的层次化索引
df.groupby('smoker', group_keys=False).apply(mean)

分组索引转成df的列

某些情况下,groupby的as_index=False参数并没有什么用,得到的还是一个series,这种情况一般是尽管分组了,但是计算需要涉及几列,最后得到的还是series,series的index是层次化索引。这里将series转成dataframe,series的层次化索引转成dataframe的列。
def fmean(df):
"""需要用两列才能计算最后的结果"""
skus=len(df['sku'].unique())
sums=df['salecount'].sum()
return sums/skus
#尽管禁用分组键,得到的还是series
salemean=data.groupby(by=['season','syear','smonth'],as_index=False).apply(fmean)
# 将series转成dataframe,顺便设置索引
sub_df = pd.DataFrame(salemean.index.tolist(),columns=salemean.index.names,index=salemean.index)
# 将groupby的结果和sub_df合并
sub_df['salemean']=salemean

桶分析与分位数

对数据切分段,然后对每一分段应用函数
frame = DataFrame({'col1':np.random.randn(1000),
'col2':np.random.randn(1000)})
#数据分段,创建分段用的因子#返回每一元素是属于哪一分割区间
factor = pd.cut(frame.col1, 4)
#分组计算,然后转成数据框形式
grouped = frame.col2.groupby(factor)
grouped.apply(myfunc).unstack()

用分组的均值填充缺失值

#自定义函数
fill_mean= lambda x:x.fillna(x.mean())
#分组填充
df.groupby(group_key).apply(fill_mean)

分组后不同的数据替换不同的值

#定义字典
fill_value = {'east':0.5, 'west':-1}
#定义函数
fill_func = lambda x:x.fillna(fill_value(x.name))
#分组填充
df.groupby(['index1','index2'...]).apply(fill_func)

sql操作

有时候觉得pandas很方便,但是有时候却很麻烦,不如SQL方便。因此pandas中也有一些例子,用pandas实现SQL的功能,简单的就不说了,下面说些复杂点的操作。 
之所以说这个复杂的语句,是因为不想将这些数据操作分写在不同的语句中,而是从头到尾连续编码实现一个功能。 
SQL复杂操作用到的主要函数是assign,简单说其实和join的功能是一样的,根据df1,df2的索引值来将df2拼接到df1上。 
两个函数是query,也听方便的。

# 有一批销量数据,筛选出那些有2个月以上的销量产品的数据,说白了就是剔除那些新上市产品的数据# 方法是先统计每个产品的数据量,然后选出那些数据量>2的产品,再在数据表中选择这些产品# sku smonth# a 1# a 2# a 3# a 4# b 5# b 6# b 7# b 8# c 9# c 10# 按sku分组,统计smonth的次数,拼接到salecount中,然后查询cnt>2的
salecount.assign(cnt=salecount.groupby(['sku'])['smonth'].count()).query('cnt>2')


打赏
赞(0) 打赏
未经允许不得转载:同乐学堂 » Pandas入门

特别的技术,给特别的你!

联系QQ:1071235258QQ群:710045715

觉得文章有用就打赏一下文章作者

非常感谢你的打赏,我们将继续给力更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫打赏

微信扫一扫打赏

error: Sorry,暂时内容不可复制!