1、数值计算和统计基础
import numpy as np
import pandas as pd
# 基本参数:axis、skipna
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'])
print(df)
print(df.mean())
print(df.mean(axis=1))
# np.nan :空值
# .mean()计算均值
# 只统计数字列
# 可以通过索引单独统计一列
# axis参数:默认为0,以列来计算,axis=1,以行来计算,这里就按照行来汇总了
print(df.mean(skipna=False))
# 主要数学计算方法,可用于Series和DataFrame(1)
df = pd.DataFrame({'key1':np.arange(10),
'key2':np.random.rand(10)*10})
print(df)
print('-----')
print(df.count(),'→ count统计非Na值的数量\n')
print(df.min(),'→ min统计最小值\n',df['key2'].max(),'→ max统计最大值\n')
print(df.quantile(q=0.75),'→ quantile统计分位数,参数q确定位置\n')
print(df.sum(),'→ sum求和\n')
print(df.mean(),'→ mean求平均值\n')
print(df.median(),'→ median求算数中位数,50%分位数\n')
print(df.std(),'\n',df.var(),'→ std,var分别求标准差,方差\n')
print(df.skew(),'→ skew样本的偏度\n')
print(df.kurt(),'→ kurt样本的峰度\n')
print('====================================')
df = pd.DataFrame({'key1':np.arange(10),
'key2':np.random.rand(10)*10})
print(df)
print(df.cumsum())
print(df.cumprod())
# 如果是随机生成的小数,累计积cumprod的结果是科学计数法
print(df.cummax())
print(df.cummin())
# 会填充key1,和key2的值
s = pd.Series(list('asdvasdcfgg'))
sq = s.unique()
print(s)
print(sq,type(sq))
print(pd.Series(sq))
# 得到一个唯一值数组
# 通过pd.Series重新变成新的Series
sq.sort()
print(sq)
# 重新排序
# 值计数:.value_counts()
print(s.value_counts())
# 得到一个新的Series,计算出不同值出现的频率
# sort参数:排序,默认为True
print('===========================================')
# 成员资格:.isin()
s = pd.Series(np.arange(10,15))
df = pd.DataFrame({'key1':list('asdcbvasd'),
'key2':np.arange(4,13)})
print(s)
print(df)
print(s.isin([5,14]))
print(df.isin(['a','bc','10',8]))
# 用[]表示
# 得到一个布尔值的Series或者Dataframe
2、数值计算和统计基础作业
import numpy as np
import pandas as pd
# 作业1:如图创建一个Dataframe(5*2,值为0-100的随机值),并分别计算key1和key2的均值、中位数、累积和
df = pd.DataFrame(np.random.rand(5, 2) * 100, columns=['key1', 'key2'])
print(df)
print(df['key1'].mean())
print(df['key2'].mean())
print(df['key1'].median())
print(df['key2'].median())
df['key1_cumsum'] = df['key1'].cumsum()
df['key2_cumsum'] = df['key2'].cumsum()
print(df)
print('====================================================')
# 作业2:写出一个输入元素直接生成数组的代码块,然后创建一个函数,该函数功能用于判断一个Series是否是唯一值数组,返回“是”和“不是”
def is_unque_series(series):
if series.is_unique:
return '是'
else:
return '否'
str = input('请输入元素,逗号分割:\n')
print(str)
s = pd.Series(str.split(','))
print(is_unque_series(s))
3、文本数据
import numpy as np
import pandas as pd
# Pandas针对字符串配备的一套方法,使其易于对数组的每个元素进行操作
# 通过str访问,且自动排除丢失/ NA值
s = pd.Series(['s', 'df', 'ds', 'a', 's', 'a', 'dd'])
df = pd.DataFrame({'key1': list('abcdef'), 'key2': ['s', 'df', 'ds', 'a', 's', 'a']})
print(s.str.count('a'))
print(df['key2'].str.upper())
# 直接通过.str调用字符串方法
# 可以对Series、Dataframe使用
# 自动过滤NaN值
print(df.columns.str.upper())
# df.columns是一个Index对象,也可使用.str
# 字符串常用方法(1) - lower,upper,len,startswith,endswith
s = pd.Series(['A','b','bbhello','123',np.nan])
print(s.str.lower(),'→ lower小写\n')
print(s.str.upper(),'→ upper大写\n')
print(s.str.len(),'→ len字符长度\n')
print(s.str.startswith('b'),'→ 判断起始是否为a\n')
print(s.str.endswith('3'),'→ 判断结束是否为3\n')
# 字符串常用方法(2) - strip
s = pd.Series([' jack', 'jill ', ' jesse ', 'frank'])
df = pd.DataFrame(np.random.randn(3, 2), columns=[' Column A ', ' Column B '],
index=range(3))
print(s)
print(df)
print('-----')
print(s.str.strip().values) # 去除字符串中的空格
print(s.str.lstrip().values) # 去除字符串中的左空格
print(s.str.rstrip().values) # 去除字符串中的右空格
# 字符串常用方法(3) - replace
df = pd.DataFrame(np.random.randn(3, 2), columns=[' Column A ', ' Column B '],
index=range(3))
df.columns = df.columns.str.replace(' ','-')
print(df)
# 替换
df.columns = df.columns.str.replace('-','hehe',n=1)
print(df)
# n:替换个数
# 字符串常用方法(4) - split、rsplit
s = pd.Series(['a,b,c','1,2,3',['a,,,c'],np.nan])
print(s.str.split(','))
print('-----')
# 类似字符串的split
print(s.str.split(',')[0])
print('-----')
# 直接索引得到一个list
print(s.str.split(',').str[0])
print(s.str.split(',').str.get(1))
print('-----')
# 可以使用get或[]符号访问拆分列表中的元素
print(s.str.split(',', expand=True))
print(s.str.split(',', expand=True, n = 1))
print(s.str.rsplit(',', expand=True, n = 1))
print('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')
# 可以使用expand可以轻松扩展此操作以返回DataFrame
# n参数限制分割数
# rsplit类似于split,反向工作,即从字符串的末尾到字符串的开头
df = pd.DataFrame({'key1':['a,b,c','1,2,3',[':,., ']],
'key2':['a-b-c','1-2-3',[':-.- ']]})
print(df['key2'].str.split('-'))
print('======================================')
# Dataframe使用split
# 字符串索引
s = pd.Series(['A','b','C','bbhello','123',np.nan,'hj'])
df = pd.DataFrame({'key1':list('abcdef'),
'key2':['hee','fv','w','hija','123',np.nan]})
print(s.str[0]) # 取第一个字符串
print(s.str[:2]) # 取前两个字符串
print(df['key2'].str[0])
# str之后和字符串本身索引方式相同
4、文本数据作业
import numpy as np
import pandas as pd
# 作业1:如图创建一个Dataframe,并分别通过字符串常用方法得到3个Series或得到新的Dataframe:
# ① name字段首字母全部大写
# ② gender字段去除所有空格
# ③ score字段按照-拆分,分别是math,english,art三个学分
df = pd.DataFrame({'gender':[' M', 'M ', ' F ', 'M', 'F '],
'name':['Jack', 'tom', 'marry', 'zack', 'Heheda'],
'score':['90-92-89','89-78-88','90-92-95','78-88-76','60-60-67']})
df['name'] = df['name'].str.capitalize()
df['gender'] = df['gender'].str.strip()
print(df['name'])
print(df['gender'].values)
df['math'] = df['score'].str.split('-', expand=True)[0]
# 也可以指定扩展出第一个元素
# df['math'] = df['score'].str.split('-', expand=True, n = 1)[0]
df['english'] = df['score'].str.split('-', expand=True)[1]
df['art'] = df['score'].str.split('-', expand=True)[2]
print(df)
5、合并
import numpy as np
import pandas as pd
# Pandas具有全功能的,高性能内存中连接操作,与SQL等关系数据库非常相似
# pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None,
# left_index=False, right_index=False, sort=True,
# suffixes=('_x', '_y'), copy=True, indicator=False)
df1 = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'],
'A': ['A0', 'A1', 'A2', 'A3'],
'B': ['B0', 'B1', 'B2', 'B3']})
df2 = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'],
'C': ['C0', 'C1', 'C2', 'C3'],
'D': ['D0', 'D1', 'D2', 'D3']})
df3 = pd.DataFrame({'key1': ['K0', 'K0', 'K1', 'K2'],
'key2': ['K0', 'K1', 'K0', 'K1'],
'A': ['A0', 'A1', 'A2', 'A3'],
'B': ['B0', 'B1', 'B2', 'B3']})
df4 = pd.DataFrame({'key1': ['K0', 'K1', 'K1', 'K2'],
'key2': ['K0', 'K0', 'K0', 'K0'],
'C': ['C0', 'C1', 'C2', 'C3'],
'D': ['D0', 'D1', 'D2', 'D3']})
print(df1)
print(df2)
print(pd.merge(df1, df2, on='key'))
print('============================================')
# left:第一个df
# right:第二个df
# on:参考键
print(df3)
print(df4)
print(pd.merge(df3, df4, on=['key1', 'key2']))
print('============================================')
# 多个链接键
# 参数how → 合并方式
print(pd.merge(df3, df4, on=['key1', 'key2'], how='inner'))
print(pd.merge(df3, df4, on=['key1', 'key2'], how='outer'))
print(pd.merge(df3, df4, on=['key1', 'key2'], how='left'))
print(pd.merge(df3, df4, on=['key1', 'key2'], how='right'))
print('----------------------------------------------------')
# inner:默认,取交集
# outer:取并集,数据缺失范围NaN
# left:按照df3为参考合并,数据缺失范围NaN
# right:按照df4为参考合并,数据缺失范围NaN
# 参数 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’为键
df2 = pd.DataFrame(range(3), index=list('abd'))
print(pd.merge(df1, df2, left_on='lkey', right_index=True))
# df1以‘key’为键,df2以index为键
# left_index:为True时,第一个df以index为键,默认False
# right_index:为True时,第二个df以index为键,默认False
# 所以left_on, right_on, left_index, right_index可以相互组合:
# left_on + right_on, left_on + right_index, left_index + right_on, left_index + right_index
# 参数 sort
df1 = pd.DataFrame({'key':list('bbacaab'),
'data1':[1,3,2,4,5,9,7]})
df2 = pd.DataFrame({'key':list('abd'),
'date2':[11,2,33]})
r1= pd.merge(df1, df2, on='key', how='outer')
print(r1)
print(pd.merge(df1, df2, on='key', sort=True, how='outer'))
print('----------------------------------------------')
# sort:按照字典顺序通过 连接键 对结果DataFrame进行排序。默认为False,设置为False会大幅提高性能
print(r1.sort_values('data1'))
# 也可直接用Dataframe的排序方法:sort_values,sort_index
# pd.join() → 直接通过索引链接
left = pd.DataFrame({'A': ['A0', 'A1', 'A2'],
'B': ['B0', 'B1', 'B2']},
index=['K0', 'K1', 'K2'])
right = pd.DataFrame({'C': ['C0', 'C2', 'C3'],
'D': ['D0', 'D2', 'D3']},
index=['K0', 'K2', 'K3'])
print(left)
print(right)
print(left.join(right))
print(left.join(right, how='outer'))
print('-----')
# 等价于:pd.merge(left, right, left_index=True, right_index=True, how='outer')
df1 = pd.DataFrame({'key':list('bbacaab'),
'data':[1,3,2,4,5,9,7]})
df2 = pd.DataFrame({'key':list('abd'),
'data':[11,2,33]})
print(df1)
print(df2)
print(pd.merge(df1, df2, left_index=True, right_index=True, suffixes=('_1', '_2')))
print('-----')
# suffixes=('_x', '_y'),当连接的结果中有相同字段时添加后缀,方便区分字段
left = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'],
'B': ['B0', 'B1', 'B2', 'B3'],
'key': ['K0', 'K1', 'K0', 'K1']})
right = pd.DataFrame({'C': ['C0', 'C1'],
'D': ['D0', 'D1']},
index=['K0', 'K1'])
print(left)
print(right)
print(left.join(right, on = 'key'))
# 等价于pd.merge(left, right, left_on='key', right_index=True, how='left', sort=False);
# left的‘key’和right的index
6、合并作业
import numpy as np
import pandas as pd
# 作业1:按要求创建Dataframe df1、df2,并合并成df3
df1 = pd.DataFrame({'key':list('abc'),
'value1':np.random.rand(3)})
df2 = pd.DataFrame({'key':list('bcd'),
'value2':np.random.rand(3)})
print(pd.merge(df1, df2, on='key', how='outer'))
# 作业2:按要求创建Dataframe df1、df2,并合并成df3
df1 = pd.DataFrame({'lkey':list('abc'),
'value1':np.random.rand(3)})
df2 = pd.DataFrame({'rkey':list('bcd'),
'value2':np.random.rand(3)})
print(pd.merge(df1, df2, left_on='lkey', right_on='rkey', how='left'))
# 作业3:按要求创建Dataframe df1、df2,并合并成df3
print(np.arange(5,8))
df1 = pd.DataFrame({'key':list('abc'),
'value1':np.random.rand(3)})
df2 = pd.DataFrame({'value1':np.random.rand(3),
'value2':np.arange(5,8)}, index=list('bcd'))
print(df2)
print(pd.merge(df1, df2, left_on='key', right_index=True, how='inner'))
7、 连接与修补
import numpy as np
import pandas as pd
# 连接与修补 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)
# 连接:concat
s1 = pd.Series([1,2,3])
s2 = pd.Series([2,3,4])
s3 = pd.Series([1,2,3],index = ['a','c','h'])
s4 = pd.Series([2,3,4],index = ['b','e','d'])
print(pd.concat([s1,s2]))
print(pd.concat([s3,s4]).sort_index())
print('-----')
# 默认axis=0,行+行
print(pd.concat([s3,s4], axis=1))
print('-----')
# axis=1,列+列,成为一个Dataframe
# 连接方式:join,join_axes
s5 = pd.Series([1,2,3],index = ['a','b','c'])
s6 = pd.Series([2,3,4],index = ['b','c','d'])
print(pd.concat([s5,s6], axis= 1))
print(pd.concat([s5,s6], axis= 1, join='inner'))
# join:{'inner','outer'},默认为“outer”。如何处理其他轴上的索引。outer为联合和inner为交集。
# print(pd.concat([s5,s6], axis= 1, join_axes=[['a','b','d']]))
# join_axes:在0.25版中已弃用
# 层次索引
sre = pd.concat([s5,s6], keys = ['one','two'])
print(sre,type(sre))
print('-----')
# keys:序列,默认值无。使用传递的键作为最外层构建层次索引
sre = pd.concat([s5,s6], axis=1, keys = ['one','two'])
print(sre,type(sre))
print('=========================================')
# axis = 1, 覆盖列名
# 修补 pd.combine_first()
df1 = pd.DataFrame([[np.nan, 3., 5.], [-4.6, np.nan, np.nan],[np.nan, 7., np.nan]])
df2 = pd.DataFrame([[-42.6, np.nan, -8.2], [-5., 1.6, 4]],index=[1, 3])
print(df1)
print(df2)
print(df1.combine_first(df2))
print('-----')
# 根据index,df1的空值被df2替代
# 如果df2的index多于df1,则更新到df1上,比如index=['a',1]
df1.update(df2)
print(df1)
# update,直接df2覆盖df1,相同index位置
8、 连接与修补作业
import numpy as np
import pandas as pd
# 作业1:按要求创建Dataframe df1、df2,并连接成df3
df1 = pd.DataFrame(np.random.rand(4,2), index=list('abcd'), columns=['values1', 'values2'])
df2 = pd.DataFrame(np.random.rand(4,2), index=list('efgh'), columns=['values1', 'values2'])
print(df1)
print(df2)
print(pd.concat([df1, df2]))
# 作业2:按要求创建Dataframe df1、df2,并用df2的值修补df1,生成df3
df1 = pd.DataFrame(np.random.rand(4,2), index=list('abcd'), columns=['values1', 'values2'])
df1.loc['b']['values1'] = np.NaN
df1.loc['c']['values1'] = np.NaN
print(df1)
print(np.arange(0, 8, step=2))
df2 = pd.DataFrame({'values1': np.arange(0, 8, step=2),
'values2': np.arange(1, 9, step=2)},
index=list('abcd'))
print(df2)
print(df1.combine_first(df2))
9、去重及替换
import numpy as np
import pandas as pd
# .duplicated / .replace
# 去重 .duplicated
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('-----')
# 判断是否重复
# 通过布尔判断,得到不重复的值
print(s.drop_duplicates())
# drop.duplicates移除重复
# inplace参数:是否替换原值,默认False
df = pd.DataFrame({'key1':['a','a',3,4,5],
'key2':['a','a','b','b','c']})
print(df)
print(df.duplicated())
print(df.drop_duplicates())
# Dataframe中使用duplicated
# 替换 .replace
s = pd.Series(list('ascaazsd'))
print(s.replace('a', 'two'))
print(s.replace(['a', 'c'], 'three'))
print(s.replace({'a': 'one', 'c': 'two'}))
# 可一次性替换一个值或多个值
# 可传入列表或字典
10、数据分组
import numpy as np
import pandas as pd
# 分组统计 - groupby功能
#
# ① 根据某些条件将数据拆分成组
# ② 对每个组独立应用函数
# ③ 将结果合并到一个数据结构中
#
# Dataframe在行(axis=0)或列(axis=1)上进行分组,将一个函数应用到各个分组并产生一个新值,然后函数执行结果被合并到最终的结果对象中。
#
# df.groupby(by=None, axis=0, level=None, as_index=True, sort=True, group_keys=True, squeeze=False, **kwargs)
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)})
print(df)
print(df.groupby('A'), type(df.groupby('A')))
# 直接分组得到一个groupby对象,是一个中间数据,没有进行计算
a = df.groupby('A').mean()
print(a, type(a))
b = df.groupby(['A', 'B']).mean()
print(b)
c = df.groupby('A')['D'].mean() # 以A分组,算D的平均值
print(c)
# 通过分组后的计算,得到一个新的dataframe
# 默认axis = 0,以行来分组
# 可单个或多个([])列分组
# 分组 - 可迭代对象
df = pd.DataFrame({'X' : ['A', 'B', 'A', 'B'], 'Y' : [1, 4, 3, 2]})
for n,g in df.groupby('X'):
print(n)
print(g)
print('----------')
# n是组名,g是分组后的Dataframe
print(df.groupby('X').get_group('A'))
print('+++++++++++')
# .get_group()提取分组后的组
print(df.groupby('X').groups) # 分组后字典的值是dataframe的索引
print(df.groupby('X').groups['A'])
# .groups:将分组后的groups转为dict
# 可以字典索引方法来查看groups里的元素
print(df.groupby('X').size())
print('==================================')
# .size():查看分组后的长度
# 其他轴上的分组
df = pd.DataFrame({'data1':np.random.rand(2),
'data2':np.random.rand(2),
'key1':['a','b'],
'key2':['one','two']})
for n,g in df.groupby(df.dtypes, axis=1):
print(n)
print(g)
# 按照值类型分列
print('============================')
# 通过字典或者Series分组
df = pd.DataFrame(np.arange(16).reshape(4,4),
columns = ['a','b','c','d'])
mapping = {'a':'one','b':'one','c':'two','d':'two','e':'three'}
print(df.groupby(mapping, axis=1).sum())
# mapping中,a、b列对应的为one,c、d列对应的为two,以字典来分组
print('----------------------')
s = pd.Series(mapping)
print(s,'\n')
print(s.groupby(s).count())
# s中,index中a、b对应的为one,c、d对应的为two,以Series来分组
# 通过函数分组
df = pd.DataFrame(np.arange(16).reshape(4,4),
columns = ['a','b','c','d'],
index = ['abc','bcd','aa','b'])
print(df.groupby(len).groups)
print(df.groupby(len).sum())
print(df.groupby(len).count())
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的分为一组
print(grouped)
print(grouped.first(),'→ first:非NaN的第一个值\n')
print(grouped.last(),'→ last:非NaN的最后一个值\n')
print(grouped.sum(),'→ sum:非NaN的和\n')
print(grouped.mean(),'→ mean:非NaN的平均值\n')
print(grouped.median(),'→ median:非NaN的算术中位数\n')
print(grouped.count(),'→ count:非NaN的值\n')
print(grouped.min(),'→ min、max:非NaN的最小值、最大值\n')
print(grouped.std(),'→ std,var:非NaN的标准差和方差\n')
print(grouped.prod(),'→ prod:非NaN的积\n')
print('---------------------------------------------------------')
# 多函数计算:agg()
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)
print(df.groupby('a').agg(['mean', np.sum]))
# print(df.groupby('a')['b'].agg({'mean1': np.mean,
# 'sum1': np.sum}))
# 报错:pandas.core.base.SpecificationError: nested renamer is not supported
# pandas 1.0版本以后写法:
print(df.groupby('a')['b'].agg([('mean1', np.mean), ('sum1', np.sum)]))
11、数据分组作业
import numpy as np
import pandas as pd
# 作业1:按要求创建Dataframe df,并通过分组得到以下结果
# ① 以A分组,求出C,D的分组平均值
# ② 以A,B分组,求出D,E的分组求和
# ③ 以A分组,得到所有分组,以字典显示
# ④ 按照数值类型分组,求和
# ⑤ 将C,D作为一组分出来,并计算求和
# ⑥ 以B分组,求出每组的均值,求和,最大值,最小值
df = pd.DataFrame({'A' : ['one', 'two', 'three', 'one','two', 'three', 'one', 'two'],
'B' : ['h', 'h', 'h', 'h', 'f', 'f', 'f', 'f'],
'C' : np.arange(10,26,2),
'D' : np.random.randn(8),
'E':np.random.rand(8)})
print(df)
print(df.groupby('A')['C'].mean())
print(df.groupby('A')['D'].mean())
print(df.groupby(['A', 'B'])['D'].sum())
print(df.groupby(['A', 'B'])['E'].sum())
print(df.groupby('A').groups)
print(df.groupby(df.dtypes, axis=1).sum()) # 注意按照数值类型分组需要加上axis=1是按照列分组
print(df.groupby({'C':'col1', 'D':'col1'}, axis=1).sum())
print('====================================')
print(df.groupby('B').mean())
print(df.groupby('B').sum())
print(df.groupby('B').max())
print(df.groupby('B').min())
# 参考答案
print('以A分组,求出C,D的分组平均值为:\n',df.groupby('A').mean(),'\n------')
print('以A,B分组,求出D,E的分组求和为:\n',df.groupby(['A','B']).sum(),'\n------')
print('以A分组,筛选出分组后的第一组数据为:\n',df.groupby('A').groups,'\n------')
print('按照数值类型分组为:\n',df.groupby(df.dtypes,axis=1).sum(),'\n------')
print('将C,D作为一组分出来,并计算求和为:\n',df.groupby({'C':'r','D':'r'},axis=1).sum(),'\n------')
print('以B分组,求出每组的均值,求和,最大值,最小值:\n',df.groupby('B').agg([np.mean,np.sum,np.max,np.min]),'\n------')
12、分组转换及一般性“拆分-应用-合并”
import numpy as np
import pandas as pd
# transform / apply
# 数据分组转换,transform
df = pd.DataFrame({'data1':np.random.rand(5),
'data2':np.random.rand(5),
'key1':list('aabba'),
'key2':['one','two','one','two','one']})
print(df)
df2 = df.groupby('key1').mean()
print(df2)
print(pd.merge(df, df2, left_on='key1', right_index=True, how='left').add_prefix('mean_')) # .add_prefix('mean_'):添加前缀
print(df.groupby('key1').transform(np.mean))
# data1、data2每个位置元素取对应分组列的均值
# 字符串不能进行计算
# 一般化Groupby方法:apply
df = pd.DataFrame({'data1':np.random.rand(5),
'data2':np.random.rand(5),
'key1':list('aabba'),
'key2':['one','two','one','two','one']})
print(df.groupby('key1').apply(lambda x: x.describe()))
# apply直接运行其中的函数
# 这里为匿名函数,直接描述分组后的统计量
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),'\n')
print(df.groupby('key1').apply(f_df2,'data2'))
print(type(df.groupby('key1').apply(f_df2,'data2')))
# f_df1函数:返回排序后的前n行数据
# f_df2函数:返回分组后表的k1列,结果为Series,层次化索引
# 直接运行f_df函数
# 参数直接写在后面,也可以为.apply(f_df,n = 2))
13、分组转换及一般性“拆分-应用-合并”作业
import numpy as np
import pandas as pd
# 作业1:按要求创建Dataframe df,通过key分组求和,并将求和结果并在原df中
df = pd.DataFrame({'data1':np.random.rand(8),
'data2':np.random.rand(8),
'key':list('aabbabab')})
print(df)
r = df.groupby('key').sum().add_suffix('_mean')
print(r)
print(pd.merge(df, r, left_on='key', right_index=True))
14、透视表及交叉表
import numpy as np
import pandas as pd
# 类似excel数据透视 - pivot table / crosstab
# 透视表:pivot_table
# pd.pivot_table(data, values=None, index=None, columns=None, aggfunc='mean', fill_value=None, margins=False, dropna=True, margins_name='All')
date = ['2017-5-1','2017-5-2','2017-5-3']*3
rng = pd.to_datetime(date)
df = pd.DataFrame({'date':rng,
'key':list('abcdabcda'),
'values':np.random.rand(9)*10})
print(df)
print(pd.pivot_table(df, values='values', index='date', columns='key', aggfunc=np.sum))
# data:DataFrame对象
# values:要聚合的列或列的列表
# index:数据透视表的index,从原数据的列中筛选
# columns:数据透视表的columns,从原数据的列中筛选
# aggfunc:用于聚合的函数,默认为numpy.mean,支持numpy计算方法
print(pd.pivot_table(df, values='values', index=['date', 'key'], aggfunc=np.min))
# 这里就分别以date、key共同做数据透视,值为values:统计不同(date,key)情况下values的平均值
# aggfunc=len(或者count):计数
# 交叉表:crosstab
# 默认情况下,crosstab计算因子的频率表,比如用于str的数据透视分析
# pd.crosstab(index, columns, values=None, rownames=None, colnames=None, aggfunc=None, margins=False, dropna=True, normalize=False)
df = pd.DataFrame({'A': [1, 2, 2, 2, 2],
'B': [3, 3, 4, 4, 4],
'C': [1, 1, np.nan, 1, 1]})
print(df)
print(pd.crosstab(df['A'],df['B']))
# 如果crosstab只接收两个Series,它将提供一个频率表。
# 用A的唯一值,统计B唯一值的出现次数
print(pd.crosstab(df['A'], df['B'], normalize=True))
# normalize:默认False,将所有值除以值的总和进行归一化 → 为True时候显示百分比
print(pd.crosstab(df['A'], df['B'], values=df['C'], aggfunc=np.sum))
# values:可选,根据因子聚合的值数组
# aggfunc:可选,如果未传递values数组,则计算频率表,如果传递数组,则按照指定计算
# 这里相当于以A和B界定分组,计算出每组中第三个系列C的值
print(pd.crosstab(df['A'],df['B'], values=df['C'], aggfunc=np.sum, margins=True))
# margins:布尔值,默认值False,添加行/列边距(小计)
15、透视表及交叉表作业
import numpy as np
import pandas as pd
# 作业1:按要求创建Dataframe df,并通过数据透视表或交叉表得到以下结果
# ① 以A列聚合,求出C,D的平均值
# ② 以A,B列聚合,求出D,E的均值、求和
# ③ 以B聚合,计算A列的元素频率
df = pd.DataFrame({'A' : ['one', 'two', 'three', 'one','two', 'three', 'one', 'two'],
'B' : ['h', 'h', 'h', 'h', 'f', 'f', 'f', 'f'],
'C' : np.arange(10,26,2),
'D' : np.random.randn(8),
'E':np.random.rand(8)})
print(df)
print(df.groupby('A').mean())
print(df.pivot_table(values=['C', 'D'], index='A', aggfunc=np.mean))
print(df.pivot_table(values=['C', 'D'], index='A', aggfunc='mean'))
print(df.pivot_table(values=['D', 'E'], index=['A', 'B'], aggfunc=['mean', 'sum']))
print(pd.crosstab(df['B'], df['A']))
16、文件读取
import numpy as np
import pandas as pd
# 核心:read_table, read_csv, read_excel
# 读取普通分隔数据:read_table
# 可以读取txt,csv
import os
os.chdir('C:/lyz/test')
data1 = pd.read_table('data1.txt', delimiter=',', engine='python')
print(data1)
# delimiter:用于拆分的字符,也可以用sep:sep = ','
# header:用做列名的序号,默认为0(第一行)
# index_col:指定某列为行索引,否则自动索引0, 1, .....
# read_table主要用于读取简单的数据,txt/csv
# 读取csv数据:read_csv
# 先熟悉一下excel怎么导出csv
data2 = pd.read_table('data2.csv', delimiter=',', engine='python', encoding='GBK')
print(data2)
# engine:使用的分析引擎。可以选择C或者是python。C引擎快但是Python引擎功能更加完备。
# encoding:指定字符集类型,即编码,通常指定为'utf-8'
# 大多数情况先将excel导出csv,再读取
print('==================================')
# 读取excel数据:read_excel
data = pd.read_excel('地市级党委书记数据库(2000-10).xlsx', sheet_name='中国人民共和国地市级党委书记数据库(2000-10)',header=0)
print(data)