流处理,听起来很高大上啊,其实就是分块读取。有这么一些情况,有一个很大的几个G的文件,没办法一次处理,那么就分批次处理,一次处理1百万行,接着处理下1百万行,慢慢地总是能处理完的。
data=pd.read_csv(file, chunksize=1000000)
for sub_df in data:
print('do something in sub_df here')
1
2
3
4
索引
Series和DataFrame都是有索引的,索引的好处是快速定位,在涉及到两个Series或DataFrame时可以根据索引自动对齐,比如日期自动对齐,这样可以省去很多事。
缺失值
pd.isnull(obj)
obj.isnull()
1
2
将字典转成数据框,并赋予列名,索引
DataFrame(data, columns=['col1','col2','col3'...],
index = ['i1','i2','i3'...])
1
2
查看列名
DataFrame.columns
查看索引
DataFrame.index
重建索引
obj.reindex(['a','b','c','d','e'...], fill_value=0]
data.index=data.index.map(str.upper)
1
2
3
4
5
列顺序重排(也是重建索引)
DataFrame.reindex[columns=['col1','col2','col3'...])`
DataFrame.reindex[index=['a','b','c'...],columns=['col1','col2','col3'...])
1
2
3
4
5
重建索引的快捷键
DataFrame.ix[['a','b','c'...],['col1','col2','col3'...]]
1
重命名轴索引
data.rename(index=str.title,columns=str.upper)
data.rename(index={'old_index':'new_index'},
columns={'old_col':'new_col'})
1
2
3
4
5
查看某一列
DataFrame['state'] 或 DataFrame.state
1
查看某一行
需要用到索引
DataFrame.ix['index_name']
1
添加或删除一列
DataFrame['new_col_name'] = 'char_or_number'
DataFrame.drop(['index1','index2'...])
DataFrame.drop(['col1','col2'...],axis=1)
del DataFrame['col1']
1
2
3
4
5
6
7
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
1
2
针对dataframe
dataframe[['col1','col2'...]]
dataframe[m:n]
dataframe[dataframe['col3'>5]]
dataframe.ix[0:3,0:5]
1
2
3
4
5
6
7
8
9
10
11
dataframe和series的运算
会根据 index 和 columns 自动对齐然后进行运算,很方便啊
方法 说明
add 加法
sub 减法
div 除法
mul 乘法
df1.add(df2,fill_value=0)
dataframe - series
规则是: | |||
---|---|---|---|
-------- | |||
v |
dataframe.sub(series,axis=0)
规则是:
-------- ---
| | | | ----->
| | | |
| | | |
| | | |
-------- ---
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
apply函数
f=lambda x:x.max()-x.min()
dataframe.apply(f)
dataframe.apply(f,axis=1)
1
2
3
4
5
6
7
排序和排名
dataframe.sort_index(axis=0, ascending=False)
dataframe.sort_index(by=['col1','col2'...])
series.rank(ascending=False)
dataframe.rank(axis=0)
1
2
3
4
5
6
7
8
9
10
11
12
13
描述性统计
方法 说明
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'])
1
2
3
处理缺失值
dataframe.dropna()
dataframe.dropna(how='all')
dataframe.dropna(how='all',axis=1)
df.fillna(0)
df.fillna({1:0.5, 3:-1})
df.fillna(df.mean())
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
将列转成行索引
df.set_index(['col1','col2'...])
1
数据清洗,重塑
合并数据集
pd.merge(df1,df2, how='inner')
pd.merge(df1,df2,left_on='l_key',right_on='r_key')
pd.merge(left, right, on=['key1','key2'],how = 'outer')
pd.merge(left, right, on='key1', suffixes=('_left','_right'))
1
2
3
4
5
6
7
8
9
10
11
12
13
14
索引上的合并
pd.merge(left, right, left_on = 'col_key', right_index=True)
pd.merge(left, right, left_on=['key1','key2'], right_index=True)
1
2
3
4
5
6
dataframe的join方法
left.join(right, how='outer')
left.join([right1,right2],how='outer')
1
2
3
4
5
6
轴向连接(更常用)
连接:concatenation
绑定:binding
堆叠:stacking
列上的连接
np.concatenation([df1,df2],axis=1) #np包
pd.concat([df1,df2], axis=1) #pd包
pd.concat([df1,df2], axis=1, join='innner')
pd.concat([df1,df2],ignore_index=True)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
合并重复数据
针对可能有索引全部或者部分重叠的两个数据集
填充因为合并时索引赵成的缺失值
where函数
np.where(isnull(a),b,a)
1
2
combine_first方法
a[:-2].combine_first(b[2:])
df1.combine_first(df2)
1
2
3
4
5
重塑层次化索引
stact:将数据转为长格式,即列旋转为行
unstack:转为宽格式,即将行旋转为列
result=data.stack()
result.unstack()
1
2
长格式转为宽格式
pivoted = data.pivot('date','item','value')
1
2
3
透视表
table = df.pivot_table(values=["Price","Quantity"],
index=["Manager","Rep"],
aggfunc=[np.sum,np.mean],
margins=True))
table.query('Manager == ["Debra Henley"]')
table.query('Status == ["pending","won"]')
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
移除重复数据
data.duplicated()`
data.drop_duplicated()
data.drop_duplicated(['key1'])
1
2
3
4
5
6
7
8
9
交叉表
是一种用于计算分组频率的特殊透视表.
注意,只对离散型的,分类型的,字符型的有用,连续型数据是不能计算频率这种东西的。
pd.crosstab(df.col1, df.col2, margins=True)
1
类似vlookup函数
利用函数或映射进行数据转换
meat_to_animal={
'bacon':'pig',
'pulled pork':'pig',
'honey ham':'cow'
}
data['new_col']=data['food'].map(str.lower).map(meat_to_animal)
1
2
3
4
5
6
7
8
9
替换值
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})
1
2
3
4
5
6
7
8
9
离散化
s=pd.Series(range(100))
pd.cut(s, bins=10, labels=range(10))
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)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
分位数分割
data=np.random.randn(1000)
pd.qcut(data,4) #四分位数
pd.qcut(data,[0,0.3,0.5,0.9,1])
1
2
3
4
5
异常值
data.describe()
col=data[3]
col[np.abs(col)>3]
data[(np.abs(data)>3).any(1)]
data[np.abs(data)>3]=np.sign(data)*3
1
2
3
4
5
6
7
8
9
10
11
12
13
抽样
df.take(np.random.permutation(len(df))[:k])
df.take(np.random.randint(0,len(df),size=k))
1
2
3
4
5
6
7
数据摊平处理
相当于将类别属性转成因子类型,比如是否有车,这个字段有3个不同的值,有,没有,过段时间买,那么将会被编码成3个字段,有车,没车,过段时间买车,每个字段用0-1二值填充变成数值型。
dummies = pd.get_dummies(df['key'],prefix='key')
df[['data1']].join(dummies)
1
2
3
4
5
字符串操作
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()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
正则表达式
正则表达式需要先编译匹配模式,然后才去匹配查找,这样能节省大量的CPU时间。
re.complie:编译
findall:匹配所有
search:只返回第一个匹配项的起始和结束地址
match:值匹配字符串的首部
sub:匹配替换,如果找到就替换
strings = 'sdf@153.com,dste@qq.com,sor@gmail.com'
pattern = r'[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}'
regex = re.compile(pattern,flags=re.IGNORECASE)
regex.findall(strings)
m = regex.search(strings) #获取匹配的地址
strings[m.start():m.end()]
regex.sub('new_string', strings)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
根据模式再切分
将模式切分,也就是将匹配到的进一步切分,通过pattern中的括号实现.
pattern = r'([A-Z0-9._%+-]+)@([A-Z0-9.-]+)\.([A-Z]{2,4})'
regex = re.compile(pattern)
regex.findall(strings)
m=regex.match(string)
m.groups()
suzyu123@163.com --> [(suzyu123, 163, com)]
matches.get(i)
1
2
3
4
5
6
7
8
9
10
11
12
13
分组聚合,计算
group_by技术
means = df['data1'].groupby([df['index1'],df['index2']).mean()
means.unstack()
1
2
3
4
5
分组后价将片段做成一个字典
pieces = dict(list(df.groupby('index1')))
pieces['b']
1
2
3
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()
1
2
3
4
5
6
7
通过字典或series进行分组
people = DataFrame(np.random.randn(5, 5),
columns=['a', 'b', 'c', 'd', 'e'],
index=['Joe', 'Steve', 'Wes', 'Jim','Travis'])
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()
1
2
3
4
5
6
7
8
9
10
11
通过函数进行分组
people.groupby(len).sum()
1
2
数据聚合
使用自定义函数
df.groupby('index1').agg(myfunc)
df.groupby('index1')['data1']describe()
1
2
3
4
5
根据列分组应用多个函数
grouped = df.groupby(['col1','col2'])
grouped['data1','data2'...].agg(['mean','std','myfunc'])
1
2
3
4
5
对不同列使用不同的函数
grouped = df.groupby(['col1','col2'])
grouped.agg({'data1':['min','max','mean','std'],
'data2':'sum'})
1
2
3
4
5
6
分组计算后重命名列名
grouped = df.groupby(['col1','col2'])
grouped.agg({'data1':[('min','max','mean','std'),('d_min','d_max','d_mean','d_std')],
'data2':'sum'})
1
2
3
4
返回的聚合数据不要索引
df.groupby(['sex','smoker'], as_index=False).mean()
1
分组计算结果添加前缀
df.groupby('index1').mean().add_prefix('mean_')
1
2
将分组计算后的值替换到原数据框
df.groupby(['index1','index2'...]).transform(np.mean)
1
2
3
更一般化的apply函数
df.groupby(['col1','col2'...]).apply(myfunc)
df.groupby(['col1','col2'...]).apply(['min','max','mean','std'])
1
2
3
禁用分组键
分组键会跟原始对象的索引共同构成结果对象中的层次化索引
df.groupby('smoker', group_keys=False).apply(mean)
1
分组索引转成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
salemean=data.groupby(by=['season','syear','smonth'],as_index=False).apply(fmean)
sub_df = pd.DataFrame(salemean.index.tolist(),columns=salemean.index.names,index=salemean.index)
sub_df['salemean']=salemean
1
2
3
4
5
6
7
8
9
10
11
12
13
桶分析与分位数
对数据切分段,然后对每一分段应用函数
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()
1
2
3
4
5
6
7
8
9
10
用分组的均值填充缺失值
fill_mean= lambda x:x.fillna(x.mean())
df.groupby(group_key).apply(fill_mean)
1
2
3
4
5
分组后不同的数据替换不同的值
fill_value = {'east':0.5, 'west':-1}
fill_func = lambda x:x.fillna(fill_value(x.name))
df.groupby(['index1','index2'...]).apply(fill_func)
1
2
3
4
5
6
7
8
sql操作
有时候觉得pandas很方便,但是有时候却很麻烦,不如SQL方便。因此pandas中也有一些例子,用pandas实现SQL的功能,简单的就不说了,下面说些复杂点的操作。
之所以说这个复杂的语句,是因为不想将这些数据操作分写在不同的语句中,而是从头到尾连续编码实现一个功能。
SQL复杂操作用到的主要函数是assign,简单说其实和join的功能是一样的,根据df1,df2的索引值来将df2拼接到df1上。
两个函数是query,也听方便的。
salecount.assign(cnt=salecount.groupby(['sku'])['smonth'].count()).query('cnt>2')
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。