pandas进阶 期中练习

Pandas进阶 期中练习

pandas进阶系列根据datawhale远昊大佬的joyful pandas教程写一些自己的心得和补充

【任务一】企业收入的多样性

【题目描述】一个企业的产业收入多样性可以仿照信息熵的概念来定义收入熵指标:
I = − ∑ i p ( x i ) log ⁡ ( p ( x i ) ) \mathrm{I}=-\sum_{\mathrm{i}} \mathrm{p}\left(\mathrm{x}_{\mathrm{i}}\right) \log \left(\mathrm{p}\left(\mathrm{x}_{\mathrm{i}}\right)\right) I=ip(xi)log(p(xi))
其中 p(xi)
是企业该年某产业收入额占该年所有产业总收入的比重。在company.csv中存有需要计算的企业和年份,在company_data.csv中存有企业、各类收入额和收入年份的信息。现请利用后一张表中的数据,在前一张表中增加一列表示该公司该年份的收入熵指标
I。
【数据下载】链接:https://pan.baidu.com/s/1leZZctxMUSW55kZY5WwgIw 密码:u6fd
【我的思路】
按公司和日期分组,求出收入额与总额的比值,并利用比值求每个项的熵再求出每个组的增益,然后按公司和日期将两表合并

import numpy as np
import pandas as pd
import warnings
warnings.filterwarnings('ignore')
df1 = pd.read_csv('../data/Company_1.csv')
df2 = pd.read_csv('../data/company_data.csv')

先看一下两个数据集的结构

df1.head()
证券代码日期
0#0000072014
1#0004032015
2#0004082016
3#0004082017
4#0004262015
df2.head()
证券代码日期收入类型收入额
012008/12/3111.084218e+10
112008/12/3121.259789e+10
212008/12/3131.451312e+10
312008/12/3141.063843e+09
412008/12/3158.513880e+08

结果是要求每个公司每年的收入熵,因此应该考虑在收入表中按企业和年份分组
查看一下分组后有没有出现收入类型重复的情况,因为如果重复的话应该把同类型的收入求和

tmp = df2[['证券代码', '日期', '收入类型']]
tmp.drop_duplicates().equals(tmp)
True

结果表明没有重复
然后按照公式一步一步求,p是每个公司每日期的比例,因此先求出每个小组的收入额的和,再求p,根据p和log p求出每一项的熵,然后求和就是每个组的信息增益,这里因为有0值,求log以后会变成无限大,无限大与0相乘后会变成空值,所以需要对空值处理一下使其为0

df2['total'] = df2.groupby(['证券代码', '日期'])['收入额'].transform('sum')
df2['ratio'] = df2['收入额'] / df2['total']
df2['entropy'] = df2['ratio']*np.log(df2['ratio'])
df2['entropy'].fillna(0, inplace=True)
df2['I'] = -df2.groupby(['证券代码', '日期'])['entropy'].transform('sum')
df2.tail()
证券代码日期收入类型收入额totalratioentropyI
9640179009572016/12/31120.006.399964e+080.0000000.0000002.178318
9640189009572016/12/31130.006.399964e+080.0000000.0000002.178318
9640199009572016/12/311452072238.976.399964e+080.081363-0.2041272.178318
9640209009572016/12/31150.006.399964e+080.0000000.0000002.178318
9640219009572016/12/311652072238.976.399964e+080.081363-0.2041272.178318
res = df2[['证券代码', '日期', 'I']].drop_duplicates()
res.head()
证券代码日期I
012008/12/312.085159
1412009/12/311.671752
2212010/12/312.108355
3412011/12/313.150479
7212012/12/312.718759

由于证券代码和日期的格式对不上,所以更改一下格式

res['证券代码'] = res['证券代码'].apply(lambda x: '#' + (6-len(str(x)))*'0' + str(x))
res['日期'] = res['日期'].apply(lambda x: int(str(x)[:4]))
res.head()
证券代码日期I
0#00000120082.085159
14#00000120091.671752
22#00000120102.108355
34#00000120113.150479
72#00000120122.718759

这里发现merge的时候需要保持两个表中的列的类型是一样的,原本在公司表中日期是int类型,而公司数据表中日期是object类型,因此在上一步做数据转换的时候要把类型也显式转换一下
最后再按照原表的顺序求信息增益

df1 = df1.merge(res, on=['证券代码', '日期'])
df1.head()
证券代码日期I
0#00000720143.070462
1#00040320152.790585
2#00040820162.818541
3#00042620153.084266
4#00042620162.988900

【使用场景】
本道题中提出的信息增益是决策树中常用的算法,用来求结点分裂时的最优分裂特征,最优分裂特征应当是信息增益(比)最高的,类似信息增益作用的算法还有基尼指数,基尼指数相对于信息增益比的优势是其计算更简便,不涉及log计算,而且是二叉树,优化了计算速度,在效率上由于信息增益比,在效果上是信息增益比的一种近似代替。
这里我根据这道题的数据再计算一下基尼指数,并分别计算一下两种算法的效率

基尼指数的公式:
Gini ⁡ ( D ) = ∑ i = 1 n p ( x i ) ∗ ( 1 − p ( x i ) ) = 1 − ∑ i = 1 n p ( x i ) 2 \begin{aligned} \operatorname{Gini}(D) &=\sum_{i=1}^{n} p\left(x_{i}\right) *\left(1-p\left(x_{i}\right)\right) &=1-\sum_{i=1}^{n} p\left(x_{i}\right)^{2} \end{aligned} Gini(D)=i=1np(xi)(1p(xi))=1i=1np(xi)2

df2['ratio_2'] = df2['ratio'] * df2['ratio']
df2 = df2.groupby(['证券代码', '日期'])['ratio_2'].sum().reset_index()
df2.head()
证券代码日期ratio_2
012008/12/310.148788
112009/12/310.230552
212010/12/310.139320
312011/12/310.057870
412012/12/310.086869
df2['gini'] = 1 - df2['ratio_2']
df2['证券代码'] = df2['证券代码'].apply(lambda x: '#' + (6-len(str(x)))*'0' + str(x))
df2['日期'] = df2['日期'].apply(lambda x: int(str(x)[:4]))
df2 = df2[['证券代码', '日期', 'gini']]
df2.head()
证券代码日期gini
0#00000120080.851212
1#00000120090.769448
2#00000120100.860680
3#00000120110.942130
4#00000120120.913131
res = res.merge(df2, on=['证券代码', '日期'])
res.head()
证券代码日期Igini
0#00000120082.0851590.851212
1#00000120091.6717520.769448
2#00000120102.1083550.860680
3#00000120113.1504790.942130
4#00000120122.7187590.913131
import seaborn as sns
sns.distplot(res['I'])

在这里插入图片描述

sns.distplot(res['gini'])

在这里插入图片描述

两个好像大致分布是一样的吧0.0
不过可以看出gini的结果更为平滑一些
再比较一下计算效率

df2 = pd.read_csv('../data/company_data.csv')
df2['total'] = df2.groupby(['证券代码', '日期'])['收入额'].transform('sum')
df2['ratio'] = df2['收入额'] / df2['total']
%%timeit
df2['entropy'] = df2['ratio']*np.log(df2['ratio'])
df2['I'] = -df2.groupby(['证券代码', '日期'])['entropy'].transform('sum')
151 ms ± 25.6 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
df2 = pd.read_csv('../data/company_data.csv')
df2['total'] = df2.groupby(['证券代码', '日期'])['收入额'].transform('sum')
df2['ratio'] = df2['收入额'] / df2['total']
df2.head()
%%timeit
df2['ratio_2'] = df2['ratio'] * df2['ratio']
df3 = df2.groupby(['证券代码', '日期'])['ratio_2'].sum().reset_index()
df3['gini'] = 1 - df3['ratio_2']
124 ms ± 21.1 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

两段代码里都包含了一个groupby的操作,因此计算不是很精确,不过还是可以看出基尼指数的计算速度相较于信息增益快了20%左右

【第二题】组队学习信息表的变换

【题目描述】请把组队学习的队伍信息表变换为如下形态,其中“是否队长”一列取1表示队长,否则为0
数据非公开,这里不提供

【我的思路】这是个宽表变长表的操作,应该是可以用wide_to_long进行操作的,但还没想好wide_to_long怎么操作。
目前我的思路是先提取出所有队长的列,然后把每个队员的列的数据按列插入到队长表中

ps.后记:提交完之后我看到了Gocara大佬的答案,明白了wide_to_long的做法,这里我在我的第一版内容之后又加了wide_to_long的做法,并比对一下两种做法的效率

teams = pd.read_excel('../data/team_info.xlsx', engine='openpyxl')
teams.head()
所在群队伍名称队长编号队长_群昵称队员1 编号队员_群昵称队员2 编号队员_群昵称.1队员3 编号队员_群昵称.2...队员6 编号队员_群昵称.5队员7 编号队员_群昵称.6队员8 编号队员_群昵称.7队员9 编号队员_群昵称.8队员10编号队员_群昵称.9
0Pandas数据分析你说的都对队5.0山枫叶纷飞6.07.0安慕希8.0信仰...NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
1Pandas数据分析熊猫人175.0鱼呲呲44.0Heaven37.0吕青50.0余柳成荫...25.0Never say never55.0K120.0Y.28.0X.Y.Q151.0swrong
2Pandas数据分析中国移不动107.0Y's124.0🥕75.0Vito146.0张小五...NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
3Pandas数据分析panda11.0太下真君35.0柚子108.0My42.0星星点灯...157.0Zys158.0不器102.0嘉平佑染NaNNaNNaNNaN
4Pandas数据分析一路向北13.0黄元帅15.016.0未期18.0太陽光下...23.0🚀169.0听风189.0CappuccinoNaNNaNNaNNaN

5 rows × 24 columns

看这个表的结构和结果集的结构,想应该可以用宽表变长表的方法做,但是没想好应该怎么弄,于是用了一种朴素的方法o.o
每列每列的填充上去

cols = list(teams.columns)
res = teams[cols[1:4]]
res['是否队长'] = 1
res.tail(2)
队伍名称队长编号队长_群昵称是否队长
20应如是54.0思无邪1
21NaNNaNNaN1

观察给出的数据的列除了前4列之外,后面的都是每两列表示一个编号和昵称,所以就循环加入到结果集中

res = res.rename(columns={'队长编号':'编号', '队长_群昵称':'昵称'})
res.head(2)
队伍名称编号昵称是否队长
0你说的都对队5.0山枫叶纷飞1
1熊猫人175.0鱼呲呲1
for i in range(4,24,2):
    c = [cols[i], cols[i+1], cols[1]]
    tmp = teams[c]
    tmp.columns = ['昵称','编号','队伍名称']
    res = pd.concat([res, tmp])
res['是否队长'].fillna(0, inplace=True)
res.head()
队伍名称编号昵称是否队长
0你说的都对队5山枫叶纷飞1.0
1熊猫人175鱼呲呲1.0
2中国移不动107Y's1.0
3panda11太下真君1.0
4一路向北13黄元帅1.0
res = res.dropna()
res = res[['是否队长', '队伍名称', '昵称', '编号']]
res.tail()
是否队长队伍名称昵称编号
10.0熊猫人28X.Y.Q
60.0Why—贰肆1MoXQian
70.0师承潘大师队159遇安
120.0没想好叫什么队117xxxxxxl
10.0熊猫人151swrong
res.shape
(146, 4)

最后得出的数据中共有146

【wide_to_long】做法,这部分我自己一开始没想出来,参考了别人的思路,自己实现了一下,我主要比较一下wide_to_long和我自己实现的concat算法的效率

df = pd.read_excel('../data/team_info.xlsx', engine='openpyxl')
df.drop(columns=['所在群'], inplace=True)
df.head(2)
队伍名称队长编号队长_群昵称队员1 编号队员_群昵称队员2 编号队员_群昵称.1队员3 编号队员_群昵称.2队员4 编号...队员6 编号队员_群昵称.5队员7 编号队员_群昵称.6队员8 编号队员_群昵称.7队员9 编号队员_群昵称.8队员10编号队员_群昵称.9
0你说的都对队5.0山枫叶纷飞6.07.0安慕希8.0信仰20.0...NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
1熊猫人175.0鱼呲呲44.0Heaven37.0吕青50.0余柳成荫82.0...25.0Never say never55.0K120.0Y.28.0X.Y.Q151.0swrong

2 rows × 23 columns

cols = ['队伍名称', '编号_队长', '昵称_队长']
for i in range(10):
    cols += [f'编号_队员{i}', f'昵称_队员{i}']
df.columns = cols
df.head(2)
队伍名称编号_队长昵称_队长编号_队员0昵称_队员0编号_队员1昵称_队员1编号_队员2昵称_队员2编号_队员3...编号_队员5昵称_队员5编号_队员6昵称_队员6编号_队员7昵称_队员7编号_队员8昵称_队员8编号_队员9昵称_队员9
0你说的都对队5.0山枫叶纷飞6.07.0安慕希8.0信仰20.0...NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
1熊猫人175.0鱼呲呲44.0Heaven37.0吕青50.0余柳成荫82.0...25.0Never say never55.0K120.0Y.28.0X.Y.Q151.0swrong

2 rows × 23 columns

res = pd.wide_to_long(df,
                stubnames=['编号', '昵称'],
                i = ['队伍名称'],
                j='是否队长',
                sep='_',
                suffix='.+')
res = res.reset_index()
res['是否队长'] = res['是否队长'].map({'队长':1}).fillna(0)
res = res.dropna()
res = res[['是否队长', '队伍名称', '昵称', '编号']]
res.head()
是否队长队伍名称昵称编号
01.0你说的都对队山枫叶纷飞5.0
11.0熊猫人鱼呲呲175.0
21.0中国移不动Y's107.0
31.0panda太下真君11.0
41.0一路向北黄元帅13.0
res.shape
(146, 4)

以上是wide_to_long的实现算法,可以看出结果是一致的
比较一下两种做法的效率:

teams = pd.read_excel('../data/team_info.xlsx', engine='openpyxl')
cols = list(teams.columns)
%%timeit
res = teams[cols[1:4]]
res['是否队长'] = 1
res = res.rename(columns={'队长编号':'编号', '队长_群昵称':'昵称'})
for i in range(4,24,2):
    c = [cols[i], cols[i+1], cols[1]]
    tmp = teams[c]
    tmp.columns = ['昵称','编号','队伍名称']
    res = pd.concat([res, tmp])
res['是否队长'].fillna(0, inplace=True)
res = res.dropna()
32.5 ms ± 3.21 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
teams = pd.read_excel('../data/team_info.xlsx', engine='openpyxl')
cols = ['队伍名称', '编号_队长', '昵称_队长']
for i in range(10):
    cols += [f'编号_队员{i}', f'昵称_队员{i}']
%%timeit
df = teams.drop(columns=['所在群'])
df.columns = cols
%timeit
res = pd.wide_to_long(df,
                stubnames=['编号', '昵称'],
                i = ['队伍名称'],
                j='是否队长',
                sep='_',
                suffix='.+')
res = res.reset_index()
res['是否队长'] = res['是否队长'].map({'队长':1}).fillna(0)
res = res.dropna()
25.5 ms ± 4.41 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

两种做法都需要一些预处理和后处理,把这些处理步骤一同考虑进去,可以看出wide_to_long比concat的做法快了20%以上

【第三题】投票情况

【题目描述】两张数据表中分别给出了county的人口数以及大选的投票情况,请解决以下问题:

  • 有多少县满足总投票数超过县人口数的一半
  • 把州(state)作为行索引,把投票候选人作为列名,列名的顺序按照候选人总票数由高到低排序,行列对应的元素为该候选人在该州获得的总票数
  • 求BT state
d1 = pd.read_csv('../data/county_population.csv')
d2 = pd.read_csv('../data/president_county_candidate.csv')
d1.head()
US CountyPopulation
0.Autauga County, Alabama55869
1.Baldwin County, Alabama223234
2.Barbour County, Alabama24686
3.Bibb County, Alabama22394
4.Blount County, Alabama57826
d2.head()
statecountycandidatepartytotal_voteswon
0DelawareKent CountyJoe BidenDEM44552True
1DelawareKent CountyDonald TrumpREP41009False
2DelawareKent CountyJo JorgensenLIB1044False
3DelawareKent CountyHowie HawkinsGRN420False
4DelawareNew Castle CountyJoe BidenDEM195034True

第一问

思路: 先求每个县的投票总人数,然后把人口表构造成州、县的形式merge以后求解

total_votes = d2.groupby(['state', 'county'])['total_votes'].sum()
pop = d1.copy()
pop['state'] = pop['US County'].apply(lambda x: str(x).split(', ')[1])
pop['county'] = pop['US County'].apply(lambda x: str(x).split(', ')[0][1:])
pop = pop.set_index(['state', 'county'])
pop.head()
US CountyPopulation
statecounty
AlabamaAutauga County.Autauga County, Alabama55869
Baldwin County.Baldwin County, Alabama223234
Barbour County.Barbour County, Alabama24686
Bibb County.Bibb County, Alabama22394
Blount County.Blount County, Alabama57826
pop = pop.join(total_votes)
pop['ratio'] = pop['total_votes'] / pop['Population']
res1 = pop[pop['ratio']>0.5]
res1.head()
US CountyPopulationtotal_votesratio
statecounty
AlabamaChoctaw County.Choctaw County, Alabama125897464.00.592899
Clarke County.Clarke County, Alabama2362213135.00.556049
Clay County.Clay County, Alabama132356930.00.523612
Colbert County.Colbert County, Alabama5524127886.00.504806
Conecuh County.Conecuh County, Alabama120676441.00.533770
res1.shape
(1434, 4)

共有1434个县投票人数超过0.5

第二问

分析目标表和原表,认为这是个长变宽的任务,所以考虑用pivot来实现,索引列是state, 值是total_votes,列是candidate,不过由于一个州有多个县有候选人的投票,所以应该先按州和候选人分组求和,再长变宽

d2.head()
statecandidatetotal_votes
0AlabamaWrite-ins7312
1AlabamaDonald Trump1441168
2AlabamaJo Jorgensen25176
3AlabamaJoe Biden849648
4AlaskaWrite-ins34210
#选择需要做运算的列
df = d2[['state', 'candidate', 'total_votes']]
#先求出候选人的票数排名
df = df.groupby('candidate')['total_votes'].sum().sort_values(ascending=False)
cols = list(df.index)
d2 = d2.groupby(['state', 'candidate'])['total_votes'].sum().reset_index()
res = d2.pivot(index='state',
              columns='candidate',
              values='total_votes')
res.head()
candidateNone of these candidatesWrite-insAlyson KennedyBill HammonsBlake HuberBrian CarrollBrock PierceBrooke PaigeChristopher LaFontaineConnie Gammon...Mark CharlesPhil CollinsPresident BoddiePrincess Jacob-FambroRichard DuncanRicki Sue KingRocky De La FuenteSheila Samm TittleTom HoeflingZachary Scalf
state
AlabamaNaN7312.0NaNNaNNaNNaNNaNNaNNaNNaN...NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
AlaskaNaN34210.0NaNNaNNaNNaN825.0NaNNaNNaN...NaNNaNNaNNaNNaNNaN318.0NaNNaNNaN
ArizonaNaN2032.0NaNNaNNaNNaNNaNNaNNaNNaN...NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
ArkansasNaNNaNNaNNaNNaN1713.02141.0NaNNaN1475.0...NaN2812.0NaNNaNNaNNaN1321.0NaNNaNNaN
CaliforniaNaN80.0NaNNaNNaNNaNNaNNaNNaNNaN...NaNNaNNaNNaNNaNNaN60155.0NaNNaNNaN

5 rows × 38 columns

这里发现了两个比较怪的候选人姓名:None of these candidatesWrite-ins
前者比较好理解,后者我查了一下,表示的含义是填选票的时候没有填已有的候选人,而是自己填了某个名字作为候选人
然后我进一步看了一下所有数据,只有Nevada州在None of these candidates列有值,而且Nevada在Write-ins列是空值,因此根据这两列的语义,有理由认为这两列表示的是一个意思,只不过Nevada州的说法不一样。

所以我将原数据集更改了一下,吧Nevada的None of these candidates列的值填到Write-ins列并删除了None of these candidates列。

res.loc['Nevada'][' Write-ins'] = res.loc['Nevada'][' None of these candidates']
res.drop(columns=[' None of these candidates'], inplace=True)
#删了这一列之后别忘了删掉前面排好序的列名
del cols[cols.index(' None of these candidates')]

最后一步:调整列顺序,填充值

res = res[cols]
res.fillna(0, inplace=True)
res.head()
candidateJoe BidenDonald TrumpJo JorgensenHowie HawkinsWrite-insRocky De La FuenteGloria La RivaKanye WestDon BlankenshipBrock Pierce...Tom HoeflingRicki Sue KingPrincess Jacob-FambroBlake HuberRichard DuncanJoseph KishoreJordan ScottGary SwingKeith McCormicZachary Scalf
state
Alabama849648.01441168.025176.00.07312.00.00.00.00.00.0...0.00.00.00.00.00.00.00.00.00.0
Alaska153405.0189892.08896.00.034210.0318.00.00.01127.0825.0...0.00.00.00.00.00.00.00.00.00.0
Arizona1672143.01661686.051465.00.02032.00.00.00.00.00.0...0.00.00.00.00.00.00.00.00.00.0
Arkansas423932.0760647.013133.02980.00.01321.01336.04099.02108.02141.0...0.00.00.00.00.00.00.00.00.00.0
California11109764.06005961.0187885.081025.080.060155.051036.00.00.00.0...0.00.00.00.00.00.00.00.00.00.0

5 rows × 37 columns

第三问

这里我将得票率定义为候选人在某州得票数与该州总人数的比值
第一步先求出bt值
求出candidate为b和t的项,缩减运算规模

d2 = pd.read_csv('../data/president_county_candidate.csv')
d2 = d2[(d2['candidate']=='Joe Biden') | (d2['candidate']=='Donald Trump')]
d2.head()
statecountycandidatepartytotal_voteswon
0DelawareKent CountyJoe BidenDEM44552True
1DelawareKent CountyDonald TrumpREP41009False
4DelawareNew Castle CountyJoe BidenDEM195034True
5DelawareNew Castle CountyDonald TrumpREP88364False
8DelawareSussex CountyDonald TrumpREP71230True
pop = d1.copy()
pop['state'] = pop['US County'].apply(lambda x: str(x).split(', ')[1])
pop['county'] = pop['US County'].apply(lambda x: str(x).split(', ')[0][1:])
pop.head()
US CountyPopulationstatecounty
0.Autauga County, Alabama55869AlabamaAutauga County
1.Baldwin County, Alabama223234AlabamaBaldwin County
2.Barbour County, Alabama24686AlabamaBarbour County
3.Bibb County, Alabama22394AlabamaBibb County
4.Blount County, Alabama57826AlabamaBlount County
d2 = d2.merge(pop, on=['state', 'county'])
d2 = d2[['state', 'county', 'candidate', 'total_votes', 'Population']]
d2['ratio'] = d2['total_votes'] / d2['Population']
d2.head()
statecountycandidatetotal_votesPopulationratio
0DelawareKent CountyJoe Biden445521807860.246435
1DelawareKent CountyDonald Trump410091807860.226837
2DelawareNew Castle CountyJoe Biden1950345587530.349052
3DelawareNew Castle CountyDonald Trump883645587530.158145
4DelawareSussex CountyDonald Trump712302342250.304109
# d3 = d2.set_index(['state', 'county'])
biden = d2[d2['candidate']=='Joe Biden']
trump = d2[d2['candidate']=='Donald Trump']
d3 = pd.merge(biden, trump, on=['state', 'county'])
d3['bt'] = d3['ratio_x'] - d3['ratio_y']
d3 = d3[['state', 'county', 'bt']]
d3.head()
statecountybt
0DelawareKent County0.019598
1DelawareNew Castle County0.190907
2DelawareSussex County-0.062111
3District of ColumbiaDistrict of Columbia0.052874
4FloridaAlachua County0.143962

求每个州的中位数

d3 = d3.groupby('state')['bt'].median().reset_index()
d3[d3['bt']>0]['state']
3               California
5                 Delaware
6     District of Columbia
9                   Hawaii
25              New Jersey
Name: state, dtype: object

最后找出的州是这几个,怎么感觉有点少呀…

后记:这里我看到自己答案是五个,感觉和现实不太相符,所以询问了大家的答案,猜想是我对得票率的定义不同
上面的代码我的得票率的定义是候选人在某州得票数与该州总人数的比值
以下我再将得票率定义为候选人在某州得票数与该州总投票数的比值
重新计算一遍,除了比例这个地方的算法不一样,其他的地方和上面代码一样,所以就不多解释了

d2 = pd.read_csv('../data/president_county_candidate.csv')
res = d2.copy()
res['total'] = d2.groupby(['state', 'county'])['total_votes'].transform('sum')
res = res[(res['candidate']=='Joe Biden') | (res['candidate']=='Donald Trump')]
res['ratio'] = res['total_votes'] / res['total']
res = res[['state', 'county', 'candidate', 'ratio']]
biden = res[res['candidate']=='Joe Biden']
trump = res[res['candidate']=='Donald Trump']
d3 = pd.merge(biden, trump, on=['state', 'county'])
d3['bt'] = d3['ratio_x'] - d3['ratio_y']
d3 = d3[['state', 'county', 'bt']]
d3 = d3.groupby('state')['bt'].median().reset_index()
d3[d3['bt']>0]['state']
4               California
6              Connecticut
7                 Delaware
8     District of Columbia
11                  Hawaii
21           Massachusetts
30              New Jersey
39            Rhode Island
45                 Vermont
Name: state, dtype: object

以新的得票率定义得出结果有9个州,看来算法没有问题,是对得票率的定义有歧义造成的,找到问题所在啦!

全部完成啦!!祝自己元旦快乐!也祝愿正在看这篇文章的你元旦快乐!愿2021如你所愿!

  • 11
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值