Day7-Python综合作业1(DataWhale)
import numpy as np
import pandas as pd
import math
任务1:企业收入的多样性
一个企业的产业收入多样性可以仿照信息熵的概念来定义收入熵指标:
其中 p(x)是企业该年某产业收入额占该年所有产业总收入的比重。在company.csv中存有需要计算的企业和年份,在company_data.csv中存有企业、各类收入额和收入年份的信息。现请利用后一张表中的数据,在前一张表中增加一列表示该公司该年份的收入熵指标I
思路:
1.将company_data表转换位包含证券代码(需转换)、日期(年)、熵值的表
2.证券编码需要去除"#"后转换为INT型
3.日期取年
4.按照年分组汇总数据,求出总计,再将汇总数据与分类数据进行求值
一定要注意将小于0的数据排除干净
df_com = pd.read_csv('练习题数据/Company.csv')
print(df_com.dtypes)
df_com.head(2)
证券代码 object
日期 int64
dtype: object
证券代码 | 日期 | |
---|---|---|
0 | #000007 | 2014 |
1 | #000403 | 2015 |
df_com_data = pd.read_csv('练习题数据/Company_data.csv')
df_com_data.head(2)
证券代码 | 日期 | 收入类型 | 收入额 | |
---|---|---|---|---|
0 | 1 | 2008/12/31 | 1 | 1.084218e+10 |
1 | 1 | 2008/12/31 | 2 | 1.259789e+10 |
1.首先将数据的日期转换为年,之前查看的时候以为日期列存储的是日期类型,后来发现存储的是字符串,只需要截取前四位即可。
A = list(df_com_data['日期'])
A = [i[:4] for i in A]
df_com_data['日期'] = A
df_com_data.head(2)
证券代码 | 日期 | 收入类型 | 收入额 | |
---|---|---|---|---|
0 | 1 | 2008 | 1 | 1.084218e+10 |
1 | 1 | 2008 | 2 | 1.259789e+10 |
2.将证券代码向前补0并加上"#",由于我们存储的证券代码是INT型,需要转为str之后再使用zfill填充0
B = df_com_data['证券代码']
B = ["#"+str(i).zfill(6) for i in B]
df_com_data['证券代码'] = B
df_com_data = df_com_data[df_com_data['收入额']>0]
df_com_data.head(2)
证券代码 | 日期 | 收入类型 | 收入额 | |
---|---|---|---|---|
0 | #000001 | 2008 | 1 | 1.084218e+10 |
1 | #000001 | 2008 | 2 | 1.259789e+10 |
3.求出依据证券代码,日期分组后的收入额的总和,并且需要查看是否有负值的收入额,作为异常值清除掉。此处因为在groupby的时候会将列名作为索引,因此使用了ax_index=False,方便之后排除异常值
gb_data = df_com_data.groupby(['证券代码','日期'],as_index=False)['收入额'].sum()
gb_data = gb_data.rename(columns={"收入额":"收入总额"})
gb_data.head(2)
证券代码 | 日期 | 收入总额 | |
---|---|---|---|
0 | #000001 | 2008 | 7.402176e+10 |
1 | #000001 | 2009 | 4.771900e+10 |
4.现在我们将得到的最终聚合数据与company_data进行拼接,之后求得p(i)的值
def Pi(x):Income = x['收入额']Income_ALL = x['收入总额']Pi_value = Income/Income_ALLreturn Pi_value.sum()
merge_data = df_com_data.merge(gb_data, left_on=['证券代码','日期'], right_on=['证券代码','日期'], how='left')
com_gb = merge_data.groupby(['证券代码','日期','收入类型'])[['收入额','收入总额']]
com_gb.apply(Pi)
com_gb = pd.DataFrame(com_gb.apply(Pi))
com_gb1 = com_gb.reset_index()
com_gb1 = com_gb.rename(columns = {0:'P'})
com_gb1['logP'] = com_gb1.apply(lambda x : math.log(x['P'],2) ,axis=1)
com_gb1['P*logP'] = com_gb1.apply(lambda x : x['P']*x['logP'] ,axis=1)
5.将com_gb中去掉类型,按照证券编号、日期,求得我们想要的I值,最后用merge将值拼入df_com中
com_gb2 = com_gb1.groupby(['证券代码','日期'])['P*logP'].sum()
com_gb3 = pd.DataFrame(com_gb2)
com_gb3 = com_gb3.reset_index()
com_gb3 = com_gb3.rename(columns = {'P*logP':'I'})
com_gb3['日期'] = com_gb3['日期'].astype(int) #一定要赋值
com_gb3.head()
com_gb3.dtypes
证券代码 object
日期 int32
I float64
dtype: object
注意:此处我遇到了一个问题:两张表中的日期的类型不一致,所以需要将日期类型转换为一致才能使用merge
com_data = df_com.merge(com_gb3, on = ['证券代码','日期'], how='left')
com_data.head()
证券代码 | 日期 | I | |
---|---|---|---|
0 | #000007 | 2014 | -4.429740 |
1 | #000403 | 2015 | -4.025963 |
2 | #000408 | 2016 | -4.066295 |
3 | #000408 | 2017 | NaN |
4 | #000426 | 2015 | -4.449655 |
任务2:组队学习信息表的变换
请把组队学习的队伍信息表变换为如下形态,其中“是否队长”一列取1表示队长,否则为0
1.通过read_excel读取数据,并观察数据与目标数据的差异,发现我们源数据拥有多列的编号和名称,我们需要将编号和名称转换位列,保留队伍名称,对于没有存值的编号和昵称,我们需要将他们去除
df = pd.read_excel('练习题数据/组队信息汇总表(Pandas).xlsx')
df.head(2)
所在群 | 队伍名称 | 队长编号 | 队长_群昵称 | 队员1 编号 | 队员_群昵称 | 队员2 编号 | 队员_群昵称.1 | 队员3 编号 | 队员_群昵称.2 | ... | 队员6 编号 | 队员_群昵称.5 | 队员7 编号 | 队员_群昵称.6 | 队员8 编号 | 队员_群昵称.7 | 队员9 编号 | 队员_群昵称.8 | 队员10编号 | 队员_群昵称.9 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | Pandas数据分析 | 你说的都对队 | 5 | 山枫叶纷飞 | 6 | 蔡 | 7.0 | 安慕希 | 8.0 | 信仰 | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
1 | Pandas数据分析 | 熊猫人 | 175 | 鱼呲呲 | 44 | Heaven | 37.0 | 吕青 | 50.0 | 余柳成荫 | ... | 25.0 | Never say never | 55.0 | K | 120.0 | Y. | 28.0 | X.Y.Q | 151.0 | swrong |
2 rows × 24 columns
colum = ['所在群','队伍名称','编号-0','昵称-0','编号-1','昵称-1','编号-2','昵称-2','编号-3','昵称-3','编号-4','昵称-4','编号-5','昵称-5','编号-6','昵称-6','编号-7','昵称-7','编号-8','昵称-8','编号-9','昵称-9','编号-10','昵称-10']
df.columns=colum
df.head(2)
所在群 | 队伍名称 | 编号-0 | 昵称-0 | 编号-1 | 昵称-1 | 编号-2 | 昵称-2 | 编号-3 | 昵称-3 | ... | 编号-6 | 昵称-6 | 编号-7 | 昵称-7 | 编号-8 | 昵称-8 | 编号-9 | 昵称-9 | 编号-10 | 昵称-10 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | Pandas数据分析 | 你说的都对队 | 5 | 山枫叶纷飞 | 6 | 蔡 | 7.0 | 安慕希 | 8.0 | 信仰 | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
1 | Pandas数据分析 | 熊猫人 | 175 | 鱼呲呲 | 44 | Heaven | 37.0 | 吕青 | 50.0 | 余柳成荫 | ... | 25.0 | Never say never | 55.0 | K | 120.0 | Y. | 28.0 | X.Y.Q | 151.0 | swrong |
2 rows × 24 columns
2.多列转行,我们考虑使用wide_to_long,先对列名进行整理,最后再将多余数据进行删除处理。这个过程中编号第一次转换的是float型,需要将他转换为Int型,这里使用astype; 在进行是否为队长的匹配的时候,注意一定要将取出来的值转换为list
df1 = pd.wide_to_long(df,stubnames=['编号','昵称'],i = ['所在群','队伍名称'],j = '编码',sep='-',suffix='.+')
df2 = df1[df1['编号'].notnull()]
df2 = df2.reset_index()
df2 = df2[['队伍名称','编号','昵称']]
df2['编号'] = df2['编号'].astype(int)
df2.head()