-
统计计算基础
常用参数
df = pd.DataFrame({'key1': [4, 5, 3, np.nan, 2],
'key2': [1, 2, np.nan, 4, 5],
'key3': [1, 2, 3, 'j', 'k']},
index=['a', 'b', 'c', 'd', 'e'])
df.mean() # .mean()计算均值
df['key1'].max()
df.mean(axis=1) # axis参数:默认为0,以列来计算,axis=1,以行来计算,这里就按照行来汇总了
df.mean(skipna=False) # skipna参数:是否忽略NaN,默认True,如False,有NaN的列统计结果仍未NaN
常用计算方法
df = pd.DataFrame({'key1': np.arange(10),
'key2': np.random.rand(10)*10})
df.count() # count统计非Na值的数量
df.min() # min统计最小值
df.max() # max统计最大值
df.quantile(q=0.75) # quantile统计分位数,参数q确定位置
df.sum() # sum求和
df.mean() # mean求平均值
df.median() # median求算数中位数,50%分位数
df.std() # std求标准差
df.var() # var求方差
df.skew() # skew样本的偏度
df.kurt() # kurt样本的峰度
df.cumsum() # cumsum样本的累计和
df.cumprod() # cumprod样本的累计积
df.isin(['a', 'z', '1', 8, 2]) # 判断该列中元素是否在列表中
~df.isin(['a', 'z', '1', 8, 2]) # 判断该列中元素是否不在列表中
文本数据 .str
直接调用.str字符串方法可以对Series、Dataframe使用,并自动过滤NaN值。
df = pd.DataFrame({'key1': list('abcdEfg'),
'key2': ['baza baz', 2, 4.53, 0xa, np.NaN, np.nan, "a3e3"],
'key3': [' zd f', 'bef ze3 ', ' few3', 'ba 32d ', 'efw fe', 'baf', 'fe3']})
df['key1'].str.lower() # lower小写
df['key1'].str.upper() # upper大写
df['key1'].str.len() # len字符长度
df['key2'].str.count('a') # count统计出现个数
df['key2'].str.startswith('b') # 判断起始是否为b
df['key3'].str.endswith('3') # 判断结束是否为3
df['key3'].str.strip() # 去除字符串前后的空格
df['key3'].str.lstrip() # 去除字符串中的左空格
df['key3'].str.rstrip() # 去除字符串中的右空格
df['key3'].str.replace(' ', '') # 替换字符串中字符
df['key3'].str.replace(' ', '', n=1) # 替换字符串中字符,n:替换个数
df['key3'].str.split(' ') # 分割成[]
df['key3'].str.split(' ', expand=True) # expand分割后扩展新,列返回DataFrame
df['key3'].str.split(' ', expand=True, n=1) # n参数限制分割数
df['key3'].str.rsplit(' ', expand=True, n=1) # 反向工作,即从字符串的末尾到字符串的开头
df['key3'].str.get(2) # get或[]符号访问拆分列表中的元素
df['key3'].str[:3]
合并 merge、join
Pandas具有功能全面的高性能内存中连接操作,与SQL等关系数据库非常相似。
Pandas提供了一个单独的merge()
函数,作为DataFrame对象之间所有标准数据库连接操作的入口。
参数 | 说明 |
---|---|
left | 一个DataFrame对象。 |
right | 另一个DataFrame对象。 |
on | 列(名称)连接,必须在左和右DataFrame对象中存在(找到)。 |
left_on | 左侧DataFrame中的列用作键,可以是列名或长度等于DataFrame长度的数组。 |
right_on | 来自右的DataFrame的列作为键,可以是列名或长度等于DataFrame长度的数组。 |
left_index | 如果为True,则使用左侧DataFrame中的索引(行标签)作为其连接键。 在具有MultiIndex(分层)的DataFrame的情况下,级别的数量必须与来自右DataFrame的连接键的数量相匹配。 |
right_index | 与右DataFrame的left_index具有相同的用法。 |
how | 它是left, right, outer以及inner之中的一个,默认为内inner。 下面将介绍每种方法的用法。 |
sort | 按照字典顺序通过连接键对结果DataFrame进行排序。默认为True,设置为False时,在很多情况下大大提高性能。 |
merge合并
left = pd.DataFrame({
'id': [1, 2, 3, 4, 5],
'Name': ['Alex', 'Amy', 'Allen', 'Alice', 'Ayoung'],
'subject_id': ['sub1', 'sub2', 'sub4', 'sub6', 'sub5']})
right = pd.DataFrame(
{'id': [1, 2, 3, 4, 5],
'Name': ['Billy', 'Brian', 'Bran', 'Bryce', 'Betty'],
'subject_id': ['sub2', 'sub4', 'sub3', 'sub6', 'sub5']})
print(left)
print("========================================")
print(right)
pd.merge(left,right,on='id')#在一个键上合并两个数据帧
pd.merge(left,right,on=['id','subject_id'])#合并多个键上的两个数据框
参数how
合并方法 | SQL等效 | 描述 |
---|---|---|
left | LEFT OUTER JOIN | 使用左侧对象的键 |
right | RIGHT OUTER JOIN | 使用右侧对象的键 |
outer | FULL OUTER JOIN | 使用键的联合 |
inner | INNER JOIN | 使用键的交集 |
pd.merge(left, right, on='subject_id', how='left')#Left Join 按照left为参考合并,数据缺失范围NaN
pd.merge(left, right, on='subject_id', how='right')#Right Join 按照right为参考合并,数据缺失范围NaN
pd.merge(left, right, how='outer', on='subject_id')#Outer Join 取并集
pd.merge(left, right, on='subject_id', how='inner')#Inner Join 取交集
参数left_on, right_on, left_index, right_index
# 参数 left_on, right_on, left_index, right_index
# 当键不为一个列时,可以单独设置左键与右键。可以相互组合。
df1 = pd.DataFrame({'lkey':list('bbacaab'),
'data1':range(7)})
df2 = pd.DataFrame({'rkey':list('abd'),
'date2':range(3)})
print(pd.merge(df1, df2, left_on='lkey', right_on='rkey'))# df1以‘lkey’为键,df2以‘rkey’为键
df1 = pd.DataFrame({'key':list('abcdfeg'),
'data1':range(7)})
df2 = pd.DataFrame({'date2':range(100,105)},
index = list('abcde'))
print(pd.merge(df1, df2, left_on='key', right_index=True))
# df1以‘key’为键,df2以index为键
# left_index:为True时,第一个df以index为键,默认False
# right_index:为True时,第二个df以index为键,默认False
参数sort
按照字典顺序通过 连接键 对结果DataFrame进行排序。默认为False,设置为False会大幅提高性能
也可直接用Dataframe的排序方法:sort_values,sort_index
。
df1 = pd.DataFrame({'key': list('bbacaab'),
'data1': [1, 3, 2, 4, 5, 9, 7]})
df2 = pd.DataFrame({'key': list('abd'),
'date2': [11, 2, 33]})
x1 = pd.merge(df1, df2, on='key', how='outer')
x2 = pd.merge(df1, df2, on='key', sort=True, how='outer')
print(x1)
print(x2)
print(x2.sort_values('data1'))
通过索引链接join
df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2'],
'B': ['B0', 'B1', 'B2']},
index=['K0', 'K1', 'K2'])
df2 = pd.DataFrame({'C': ['C0', 'C2', 'C3'],
'D': ['D0', 'D2', 'D3']},
index=['K0', 'K2', 'K3'])
print(df1)
print(df2)
print(df1.join(df2))
print(df1.join(df2, how='outer'))
# 等价于:pd.merge(left, right, left_index=True, right_index=True, how='outer')
print(df1.join(df2, how='inner'))
# 等价于:pd.merge(left, right, left_index=True, right_index=True, how='inner')
df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'],
'B': ['B0', 'B1', 'B2', 'B3'],
'key': ['K0', 'K1', 'K0', 'K1']})
df2 = pd.DataFrame({'C': ['C0', 'C1'],
'D': ['D0', 'D1']},
index=['K0', 'K1'])
print(df1.join(df2, on='key'))
# 等价于pd.merge(left, right, left_on='key', right_index=True, how='left', sort=False);
# left的‘key’和right的index
连接与修补concat、combine_first
连接 - 函数完成了沿轴执行级联操作的所有重要工作。
pd.concat(objs, axis=0, join='outer', join_axes=None, ignore_index=False,
keys=None, levels=None, names=None, verify_integrity=False,
copy=True)
s1 = pd.Series([1, 2, 3], index=['a', 'c', 'h'])
s2 = pd.Series([2, 3, 4], index=['b', 'e', 'd'])
print(pd.concat([s1, s2]))
print(pd.concat([s1, s2]).sort_index())
# 默认axis=0,行+行
print(pd.concat([s1, s2], axis=1))
# axis=1,列+列,成为一个Dataframe
# join:{'inner','outer'},默认为“outer”。如何处理其他轴上的索引。outer为联合和inner为交集。
print(pd.concat([s1, s2], axis=1, join='inner'))
# join_axes:指定联合的index
print(pd.concat([s1, s2], axis=1, join_axes=[['a', 'b', 'd']]))
# keys:序列,默认值无。使用传递的键作为最外层构建层次索引
print(pd.concat([s1, s2], keys=['one', 'two']))
# axis = 1, 覆盖列名
print(pd.concat([s1, s2], axis=1, keys=['one', 'two']))
# 根据index,df1的空值被df2替代
# 如果df2的index多于df1,则更新到df1上,比如index=['a',1]
print(s1.combine_first(s2))
# update,直接s2覆盖s1,相同index位置
print(s1.update(s2))
去重及替换.duplicated / .replace
s = pd.Series([1, 1, 1, 1, 2, 2, 2, 3, 4, 5, 5, 5, 5])
print(s.duplicated()) # 判断是否重复
print(s[s.duplicated() == False]) # 不重复的值
print(s.drop_duplicates()) # 移除重复 inplace参数:是否替换原值,默认False
s = pd.Series(list('ascaazsd'))
print(s.replace('a', np.nan)) # 可一次性替换一个值或多个值
print(s.replace(['a', 's'], np.nan)) # 可传入列表
print(s.replace({'a': 'zzzzz!', 's': 123})) # 可传入字典
数据分组.groupby
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)})
# 直接分组得到一个groupby对象,是一个中间数据,没有进行计算
print(df.groupby('A')) # 默认axis = 0,以行来分组
df.groupby('A').mean()
df.groupby(['A', 'B']).mean() # 可单个或多个([])列分组
df.groupby(['A'])['D'].mean() # 以A分组,算D的平均值
df = pd.DataFrame({'X': ['A', 'B', 'A', 'B'],
'Y': [1, 4, 3, 2]})
print(list(df.groupby('X'))) # 可迭代对象,直接生成list
print(list(df.groupby('X'))[0]) # 以元祖形式显示
for n, g in df.groupby('X'):
# n是组名,g是分组后的Dataframe
print(n)
print(g)
print('-----')
print(df.groupby(['X']).get_group('A')) # .get_group()提取分组后的组
# .groups:将分组后的groups转为dict,索引方法来查看groups里的元素
print(df.groupby(['X']).groups['A'])
print(df.groupby(['X']).size()) # .size():查看分组后的长度
df = pd.DataFrame({'data1': np.random.rand(2),
'data2': np.random.rand(2),
'key1': ['a', 'b'],
'key2': ['one', 'two']})
print(df.dtypes)
for n, p in df.groupby(df.dtypes, axis=1):
# 按照行值类型分列
print(n)
print(p)
print('-----')
s = pd.Series([1, 2, 3, 10, 20, 30], index=[1, 2, 3, 1, 2, 3])
grouped = s.groupby(level=0) # 唯一索引用.groupby(level=0),将同一个index的分为一组
grouped.first() # first:非NaN的第一个值
grouped.last() # last:非NaN的最后一个值
grouped.sum() # sum:非NaN的和
grouped.mean() # mean:非NaN的平均值
grouped.median() # median:非NaN的算术中位数
grouped.count() # count:非NaN的值
grouped.min() # min、max:非NaN的最小值、最大值
grouped.std() # std,var:非NaN的标准差和方差
grouped.prod() # prod:非NaN的积
df = pd.DataFrame({'a': [1, 1, 2, 2],
'b': np.random.rand(4),
'c': np.random.rand(4),
'd': np.random.rand(4), })
print(df.groupby('a').agg(['mean', np.sum]))
# 函数写法可以用str,或者np.方法
# 可以通过list,dict传入,当用dict时,key名为columns
print(df.groupby('a')['b'].agg({'result1': np.mean, 'result2': np.sum}))
分组转换及一般性“拆分-应用-合并”.transform .apply
df = pd.DataFrame({'data1': np.random.rand(5),
'data2': np.random.rand(5),
'key1': list('aabba'),
'key2': ['one', 'two', 'one', 'two', 'one']})
k_mean = df.groupby('key1').mean()
print(k_mean)
print(pd.merge(df, k_mean, left_on='key1', right_index=True).add_prefix(
'mean_')) # .add_prefix('mean_'):添加前缀。通过分组、合并,得到一个包含均值的Dataframe
print(df.groupby('key2').mean()) # 按照key2分组求均值
# data1、data2每个位置元素取对应分组列的均值。字符串不能进行计算
print(df.groupby('key2').transform(np.mean))
一般化Groupby方法.apply
df = pd.DataFrame({'data1': np.random.rand(5),
'data2': np.random.rand(5),
'key1': list('aabba'),
'key2': ['one', 'two', 'one', 'two', 'one']})
# apply直接运行其中的函数。
print(df.groupby('key1').apply(lambda x: x.describe())) # 匿名函数,直接描述分组后的统计量
def f_df1(d, n):
return(d.sort_index()[:n])
def f_df2(d, k1):
return(d[k1])
print(df.groupby('key1').apply(f_df1, 2)) # f_df1函数:返回排序后的前n行数据
# f_df2函数:返回分组后表的k1列,结果为Series,层次化索引
# 参数直接写在后面,也可以为.apply(f_df,n = 2))
print(df.groupby('key1').apply(f_df2, 'data2'))
透视表.pivot table
数据透视表(Pivot Table)是一种交互式的表,可以进行某些计算,如求和与计数等。所进行的计算与数据跟数据透视表中的排列有关。之所以称为数据透视表,是因为可以动态地改变它们的版面布置,以便按照不同方式分析数据,也可以重新安排行号、列标和页字段。每一次改变版面布置时,数据透视表会立即按照新的布置重新计算数据。另外,如果原始数据发生更改,则可以更新数据透视表。
date = ['2019-4-1', '2019-4-2', '2019-4-3']*3
rng = pd.to_datetime(date)
df = pd.DataFrame({'date': rng,
'key': list('abcdabcda'),
'values': np.random.rand(9)*10})
#想移除NaN使用“fill_value”将其设置为0
# data:DataFrame对象
# values:要聚合的列或列的列表
# index:数据透视表的index,从原数据的列中筛选
# columns:数据透视表的columns,从原数据的列中筛选
# aggfunc:用于聚合的函数,默认为numpy.mean,支持numpy计算方法
print(pd.pivot_table(df, values='values',
index='date', columns='key', aggfunc=np.sum))
# 这里就分别以date、key共同做数据透视,值为values:统计不同(date,key)情况下values的平均值
# aggfunc=len(或者count):计数
print(pd.pivot_table(df, values='values', index=['date', 'key'], aggfunc=len))
交叉表.crosstab
# 交叉表:crosstab
# 默认情况下,crosstab计算因子的频率表,比如用于数据透视分析
df = pd.DataFrame({'A': [1, 2, 2, 2, 2],
'B': [3, 3, 4, 4, 4],
'C': [1, 1, np.nan, 1, 1]})
# 如果crosstab只接收两个DataFrame,它将提供一个频率表。
# 用A的唯一值,统计B唯一值的出现次数
print(pd.crosstab(df['A'],df['B']))
print(pd.crosstab(df['A'],df['B'],normalize=True))# normalize:默认False,将所有值除以值的总和进行归一化
# values:可选,根据因子聚合的值数组
# aggfunc:可选,如果未传递values数组,则计算频率表,如果传递数组,则按照指定计算
# 这里相当于以A和B界定分组,计算出每组中第三个系列C的值
print(pd.crosstab(df['A'],df['B'],values=df['C'],aggfunc=np.sum))
# margins:布尔值,默认值False,添加行/列边距(小计)
print(pd.crosstab(df['A'],df['B'],values=df['C'],aggfunc=np.sum, margins=True))
数据读取
import os
os.chdir('D:/')
# delimiter:用于拆分的字符,也可以用sep:sep = ','
# header:用做列名的序号,默认为0(第一行)
# index_col:指定某列为行索引,否则自动索引0, 1, .....
data = pd.read_table('data.txt', delimiter=',')
data = pd.read_table('data.txt', delimiter=',',
header=0, index_col=1) # 用于读取简单的数据
# engine:使用的分析引擎。可以选择C或者是python。C引擎快但是Python引擎功能更加完备。
# encoding:指定字符集类型,即编码,通常指定为'utf-8'
data = pd.read_csv('data.csv', encoding='utf-8')
# io :文件路径。
# sheetname:返回多表使用sheetname=[0,1],若sheetname=None是返回全表。① int/string 返回的是dataframe ②而none和list返回的是dict
# header:指定列名行,默认0,即取第一行
# index_col:指定列为索引列,也可以使用u”strings”
data = pd.read_excel('data.xlsx', sheetname='Sheet1', header=0)
网友评论