美文网首页
python合道-常规Pandas(2)

python合道-常规Pandas(2)

作者: oopp8 | 来源:发表于2019-04-28 18:37 被阅读0次
  • 统计计算基础

常用参数

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)

相关文章

网友评论

      本文标题:python合道-常规Pandas(2)

      本文链接:https://www.haomeiwen.com/subject/lpnxnqtx.html