pandas学习-中期测试

第一题待补。第二题和第三题都有十分详细的思考过程和解决步骤。

第二题

在这里插入图片描述

【思考】:
看到问题,首先应该做的就是拆分问题!!!这一步非常重要,把大问题拆成一个个能解决的小问题,就可以帮助我们一步步理解推敲。

原数据展示:
在这里插入图片描述
先观察原数据表格,我们可以发现,原数据每一行代表一个队伍,一共有21支队伍,并且每个队伍的人数是不一致的。那么自然而然问题就显现出来了:

1、我怎么才能取到每一支队伍的人数呢?
继续将上述问题进行拆解!要求出每一支队伍的人数,我可以先求第一支队伍的人数,然后再做处理求每一支队伍的。

【解答】:我一开始想的是得到非零元素的索引来处理计算出人数,但后来发现我可以使用内置方法count给一行里面的所有元素计数,因为计算出来的就是非零元素的个数,再对此做减法和除法的处理,即可得到每个队伍的人数了)

df.loc[0].count()  ## 查看一行有多少非零元素
sig_num = (df.loc[0].count()-2) / 2  ## 求出第一个队伍有多少人
df['队伍名称'].count()  ## 求出一共有多少个队伍

## 求出每一个队伍有多少人
each_num = [(df.loc[i].count()-2) / 2 for i in range(df['队伍名称'].count())]
each_num

输出:[5.0, 11.0, 6.0, 9.0, 9.0, 4.0, 10.0, 10.0, 3.0, 8.0, 7.0, 9.0, 10.0, 3.0, 5.0, 9.0, 7.0, 4.0, 8.0, 7.0, 2.0]

2、对比题目要求的表格,我们需要新建一个DataFrame,行索引为人的总数序号,列索引为[‘是否队长’,‘队伍名称’,‘昵称’,‘编号’]。

新建一个目标表格大小的空DataFrame

## 新建一个目标表大小的空表
df_team = pd.DataFrame(columns= ['是否队长','队伍名称','昵称','编号'],
                      index = [i for i in range(int(peo_sum))])
df_team 

3、现在需要根据每一支队伍的人数来将表格的「队伍名称」这一列进行填写。同样拆解问题,先尝试把第一支队伍的名称写入。

df_team.iloc[0:int(sig_num[0]),1:2] = df.iloc[0,1] ## 根据第一支队伍的人数,将队名写入表中

然后就需要把所有队伍写入,这里需要注意索引的问题。队伍人数的列表:[5.0, 11.0, 6.0, 9.0, 9.0, 4.0…] ,第0-4的位置应该为第一支队伍,第5-15的位置应该为第二支队伍,16-21是第三支队伍,依次发现规律!其实就是需要将前面填写了的队伍人数进行加和,这样才能保证后面的序列是正确的。我最开始用的是[i-1]与[i]的切片,发现完全不对,才把数字列出来看看是哪里出现了问题,才发现原来是需要加和。

## 正确的做法    根据每一支队伍的人数,将其队名写入表中
num_sum = 0
for i in range(len(sig_num)):
    df_team.iloc[num_sum:num_sum+int(sig_num[i]),1:2] = df.iloc[i,1]
    num_sum += int(sig_num[i])
df_team

在这里插入图片描述
那么现在就应该来考虑写入编号和昵称的问题啦。注:是否队长那一列是我通过df_team ['是否队长'] = 0将其置零的,后面会根据编号来将队长置1,下面步骤会详细写。

4、现在就是需要取出昵称与编号了。同样我们先拆解问题,先把第一行,即第一支队伍的人员取出来,并存入到DataFrame中。

## 取出第一行的元素,即第一支队伍中所有人的编号和昵称
[df.iloc[0,j] for j in range(2,df.loc[0].count())]

输出:[5, '山枫叶纷飞 ', 6, '蔡 ', 7.0, '安慕希 ', 8.0, '信仰', 20.0, 'biubiu🙈🙈']

## 只放一个队员的昵称和编号进去
df_team.iloc[0,3] = row0[0]
df_team.iloc[0,2] = row0[1]
df_team

## 尝试将第一行所有的昵称和编号写入df_team表中
for i in range(0, len(row0), 2):
    df_team.iloc[i,3] = row0[i]
    df_team.iloc[i,2] = row0[i+1]
df_team

此时就出现了一个问题,步长为2,虽然满足了昵称和编号信息的读取,但却会导致写入一行空一行的情况。所以这是错误的,之后会介绍改进方法。
不过我们可以发现,这种将昵称与编号存入到列表的方法是可以拓展的,所以我们就又延伸出一个步骤了,将所有人员的昵称与编号信息,都存入一个列表里面。

5、将所有人员的昵称与编号信息存入一个列表里面。

sum_info = [df.iloc[i,j] for i in range(df['队伍名称'].count()) for j in range(2,df.loc[i].count())]
sum_info

输出:[5, '山枫叶纷飞 ', 6, '蔡 ', 7.0, '安慕希 ', 8.0, '信仰', 20.0, 'biubiu🙈🙈',
 175, '鱼呲呲', 44, 'Heaven', 37.0, '吕青', 50.0, '余柳成荫', 82.0, 'Kuroe', 60.0, '啊翟翟', 25.0, 'Never say never', 55.0, 'K', 120.0, 'Y.', 28.0, 'X.Y.Q', 151.0, 'swrong',
 107, "Y's", 124, '🥕', 75.0, 'Vito', 146.0, '张小五', 186.0, 'Rain Forest', 94.0, '蓝齐儿', 
 11, '太下真君', 35, '柚子', 108.0, 'My', 42.0, '星星点灯', 45.0, '小茉莉~', 121.0, '什影',  157.0, 'Zys', 158.0, '不器', 102.0, '嘉平佑染', 
 13, '黄元帅', 15, '化', 16.0, '未期', 18.0, '太陽光下', 19.0, '李小葵', 22.0, 'Tracey_chen', 23.0, '🚀', 169.0, '听风', 189.0, 'Cappuccino',
 149, '老狼', 51, 'Robin or Michael', 72.0, '慕安春临', 160.0, '哦豁',
 48, 'Cliff', 81, 'ww', 147.0, '小清新', 47.0, '哈桑的雨天', 125.0, 'H', 71.0, '似曾的相识', 119.0, '可口可乐与果粒橙', 92.0, '一代天骄', 139.0, 'xg', 1.0, 'MoXQian', 
  33, 'Tango', 49, '拿铁', 100.0, '懵懂出茅庐', 52.0, 'Esther', 109.0, 'L', 144.0, 'HL', 38.0, '栗子', 162.0, '落叶', 150.0, '小浣熊', 159.0, '遇安', 
 181, '阿煜', 31, 'Bartender', 70.0, '林木木', 
 96, '夏洛克', 168, '嘿', 98.0, 'Gocara', 83.0, '鉹', 113.0, '叶夏', 67.0, 'jo', 93.0, 'Lance', 34.0, '☁️ ', 
 180, '星', 167, 'swordsman', 32.0, '陈易男', 161.0, 'zzx', 110.0, '龙卷风', 43.0, '我是王王王的微信', 111.0, '#Paletteboo ', 
 2, 'Lyndsey', 90, 'Roman.', 91.0, '李松泽 Orwell', 115.0, 'L.', 163.0, '阿涂', 68.0, 'YHY', 62.0, '佬仔', 30.0, 'JWJ', 154.0, '👀', 
 4, '王瑞楠', 64, 17, 73.0, '叶', 46.0, '山茶', 177.0, 'sen', 122.0, '海角七号', 24.0, '清风', 153.0, '小闹', 78.0, '罐罐儿', 117.0, 'xxxxxxl', 
 26, '木南居士', 187, '冻草莓', 61.0, 'Shawn', 
 27,'daydayup', 183, '郝翊 Eva', 182.0, '辣白菜', 138.0, '时代的病人', 80.0, 'xcz', 
 9, 'AI', 106, 'moon', 87.0, '快乐的貔貅', 12.0, '双手', 66.0, 'Aquatic', 99.0, '彭舒凡', 10.0, '天国之影', 170.0, 'WinqiHe', 17.0, '王婷-TeneT', 
 3, '苏limin', 74, 'carlos', 56.0, 'maybe', 156.0, 'glow', 40.0, 'GEGURI', 41.0, 'pick球', 136.0, 'lun', 
 21, '阿芒Aris', 152,'Alex', 95.0, 'Jie', 104.0, '梦想家', 
 103, 'Co', 137, 'Z.', 69.0, 'Albert', 76.0, '方', 86.0, '晓剑', 155.0, 'spike', 85.0, '慕明智', 133.0, '小菜鸡', 
 14, '卡鲁鼙欧!', 140, 'Radio', 105.0, '减肥的卡比兽', 118.0, '好奇宝宝', 63.0, 'Daisy', 131.0, 'One Better', 112.0, 'rain', 54, '思无邪', 58, 'Justzer0']

6、将所有队员的昵称和编号写入进表中:

for i in range(0, int(len(sum_info)/2)):
    df_team.iloc[i,3] = sum_info[i*2]
    df_team.iloc[i,2] = sum_info[i*2+1]
df_team

7、修改「是否队长」这一列。

【思考】本来想用的是where或者mask来判断和修改值,但是有一个问题给出的布尔索引大小必须与表格一致。相当于我还是要先使用每一队的人数来做一个布尔序列。既然都要通过每一队人数来做布尔序列了,那我为何不直接将每队人数与队长的关系直接映射到表中呢。

df_team ['是否队长'] = 0  # 先将这一列全置为0
test_num = [(df.loc[i].count()-2) / 2 for i in range(df['队伍名称'].count())]
cap_id = 0
for i in range(len(test_num)):
    print(cap_id)
    df_team.iloc[int(cap_id),0] = 1
    cap_id += test_num[i]
df_team

在这里插入图片描述
终于大功告成了!!!我不会告诉大家这道题我花了几个小时的…哈哈哈。并且我也知道其中使用了太多循环啦,按照GYH大佬的话说,当你使用了循环的时候就需要思考是不是有其他pandas内置的方法来替代。我的这份答案肯定不是最优解!但是能初次把这些做出来,我就已经挺开心啦!嘻嘻嘻~

【完整代码】:
## 计算每一支队伍的人数
each_num = [(df.loc[i].count()-2) / 2 for i in range(df['队伍名称'].count())]

## 新建一个空的DataFrame
df_team = pd.DataFrame(columns= ['是否队长','队伍名称','昵称','编号'],
                      index = [i for i in range(int(peo_sum))])

## 将每一队的队名写入相应成员的「队伍名称」中
num_sum = 0
for i in range(len(sig_num)):
    df_team.iloc[num_sum:num_sum+int(sig_num[i]),1:2] = df.iloc[i,1]
    num_sum += int(sig_num[i])
df_team

## 将所有队员的昵称与编号存入列表中
sum_info = [df.iloc[i,j] for i in range(df['队伍名称'].count()) for j in range(2,df.loc[i].count())]
sum_info

## 将所有队员的昵称与编号写入DataFrame中
for i in range(0, int(len(sum_info)/2)):
    df_team.iloc[i,3] = sum_info[i*2]
    df_team.iloc[i,2] = sum_info[i*2+1]
df_team

## 修改「是否队长」这列的值
df_team ['是否队长'] = 0  # 先将这一列全置为0
test_num = [(df.loc[i].count()-2) / 2 for i in range(df['队伍名称'].count())]
cap_id = 0
for i in range(len(test_num)):
    print(cap_id)
    df_team.iloc[int(cap_id),0] = 1
    cap_id += test_num[i]
df_team

第三题

【题目介绍】:

在这里插入图片描述

【数据展示】:

county_population.csv
在这里插入图片描述
president_county_candidate.csv
在这里插入图片描述

【我的解答】:

题目1:“有多少县满足总投票数超过县人口数的一半”

【思考】

想要求出每个县的总投票人数,那么就需要把president_county_candidate.csv表里面的一个县里面投给所有人的票数求和,然后再求出county_population.csv这个表里每个县的总人数。

1、计算每个县的总投票数:

df.groupby('county')['total_votes'].sum()

这里需要注意的是,不同州里面有相同县名,所以以上做法是错误的。应为:

df.groupby(['state','county'])['total_votes'].sum()

2、将county_population.csv表中州的名字单独提出来作为表中的一列

df_popu['state'] = [df_popu['US County'][i].split(',')[1].lstrip() for i in range(df_popu['US County'].count())]
df_popu

在这里插入图片描述

3、将county_population.csv表中县的名字作为一列加入到表中:

df_popu['county'] = [df_popu['US County'][i].split(',')[0].split(' ')[0].strip('.') for i in range(df_popu['US County'].count())]
df_popu

在这里插入图片描述

现在遇上了一个问题!就是怎么才能让这两个进行比较呢?county的名字怎么对应上呢?

!!!想到啦,可以使用「连接」呀!将两个表的county值作为键来连接,再比较它们值。我去试试~

那么就需要将刚才按照县来分组,求出来的每个县的投票总数重新做一个新的表。

又有新的问题啦,让county作为键,左连接表上去。但是这样加上去state和county并不能完全匹配,有很多多余的。

4、求出两张表中「州与县组合」的交集

## 求出两张表的州、县的交集
df.groupby(['state','county'])['total_votes'].sum().index & df_popu.groupby(['state','county'])['Population'].sum().index

在这里插入图片描述
5、由于两个表的数据不一致,县名不能完全对上,所以需要做筛选。把两个表的「州与县的组合」的交集求出来。

保存交集的值:

multi_index = df.groupby(['state','county'])['total_votes'].sum().index & df_popu.groupby(
    ['state','county'])['Population'].sum().index

新建一个最终的表:

df_final = pd.DataFrame(columns= ['state','county'])

将state和county的值存进去:

df_final['state'] = [multi_index[i][0] for i in range(len(multi_index))]
df_final['county'] = [multi_index[i][1] for i in range(len(multi_index))]

在这里插入图片描述
6、将人口数量的值存入这个最终的表中:

# 将人口数量的表加入到终级表(两个表交集的州县)上
df_test = df_final
df_test.merge(df_popu, on=['state','county'], how='left')

在这里插入图片描述
那么我们现在只需要把每个州县的投票总数加入到该表中即可。

7、重复上述操作,新建表,将投票的表的每个州县的总投票数变成一列,并与上述终极表相连接。

df_index = df.groupby(['state','county'])['total_votes'].sum().index
df_index

df_votefinal = pd.DataFrame(columns= ['state','county'])
df_votefinal['state'] = [df_index[i][0] for i in range(len(df_index))]
df_votefinal['county'] = [df_index[i][1] for i in range(len(df_index))]
df_votefinal

## 根据州县分组得到的总投票数加入表中
df_votefinal['sum_vote'] = [df.groupby(['state','county'])['total_votes'].sum()[i] for i in range(len(df_index))]
df_votefinal

df_test = df_test.merge(df_votefinal, on=['state','county'], how='left')
df_test

总人数与总投票数都加入表中了,接下来就进行判断。
在这里插入图片描述
8、判断投票总数是否大雨人口总数的一半,并选出对应的行。

df_test.loc[df_test['sum_vote'] > df_test['Population'] / 2 ]

在这里插入图片描述
大功告成!!!终于做出来啦!!!一个小问我就要花几小时。。。没关系,我做出来了,做出来了就很开心。等之后看看别人的优秀方法吧~

题目2:“把州(state)作为行索引,把投票候选人作为列名,列名的顺序按照候选人在全美的总票数由高到低排序,行列对应的元素为该候选人在该州获得的总票数”

1、根据州与候选人来将投票分组。

state_peo_vote = df.groupby(['state','candidate'])['total_votes'].sum()

在这里插入图片描述
2、将上述结果转为DataFrame格式,这里介绍两种方法:.reset_index().to_frame()。这样就不用像上面我那样存索引存值再转换了,大佬的一句话让我省了太多力气啦!感谢~

state_peo_vote = state_peo_vote.reset_index()
state_peo_vote

在这里插入图片描述
3、计算每一位候选人的总票数,降序排列

# 计算每一位候选人的总票数
df.groupby('candidate')['total_votes'].sum()  
# 计算每一位候选人的总票数并降序排列
df.groupby('candidate')['total_votes'].sum().sort_values(ascending=False)

在这里插入图片描述
4、长表转为宽表,将州作为行索引,列索引为候选人名字。

sort_df = state_peo_vote.pivot(index='state', columns = 'candidate', values='total_votes')
sort_df

5、修改列索引的顺序,将候选人的顺序变为以总票数由高到低排列。
(其实我最开始是想再pivot转换的时候将columns的值写为df_columns这个列表,但是报错啦,所以才想到直接修改列名顺序。)

sort_df.columns = df_columns
sort_df

截取了表的一部分。
在这里插入图片描述
题目3: “每一个州下设若干县,定义拜登在该县的得票率减去川普在该县的得票率为该县的BT指标,若某个州所有县BT指标的中位数大于0,则称该州为Biden State,请找出所有的Biden State。”

1、看下每位候选者在各个地方的投票情况

df_can_vote = df.groupby(['state','county','candidate'])['total_votes'].sum()
df_can_vote = df_can_vote.reset_index()
df_can_vote

2、避免两张表连接时的问题,修改投票的列名:

df_can_vote.rename(columns={'total_votes':'votes'},inplace=True)
df_can_vote.columns

3、选出只包含川普和拜登的行:

df_two_vote = df_can_vote.loc[df_can_vote['candidate'].isin(['Donald Trump', 'Joe Biden']) ]
df_two_vote

在这里插入图片描述
4、根据州县求出每个地方的总票数。

df_sum_vote = df.groupby(['state','county'])['total_votes'].sum()
df_sum_vote = df_sum_vote.reset_index()
df_sum_vote

在这里插入图片描述

5、将两张表连接起来,就可以知道每个地区总票数以及川普和拜登分别的票数:

df_merge = df_sum_vote.merge(df_two_vote, on=['state','county'], how='left')
df_merge

在这里插入图片描述
6、将拜登和川普各自的得票数除以总票数,得到占比率percent。

df_merge['percent'] = df_merge.votes/df_merge.total_votes
df_merge

7、求BT值,每个州只保留一行,并把BT值加入到表中

BT = df_merge.iloc[1:len(df_merge['percent']):2,5].values - df_merge.iloc[0:len(df_merge['percent']):2,5].values
BT
df_state_vote = df_merge.loc[df_merge['candidate'] == 'Donald Trump' ]
df_state_vote
df_state_vote['BT'] = BT
df_state_vote

在这里插入图片描述

8、求一个州中所有县的值的中位数。

# 一个州中所有县的BT中位数
state_median = df_state_vote.groupby('state')['BT'].median()
state_median = state_median.reset_index()
state_median.rename(columns={'BT':'median'},inplace=True)
state_median

在这里插入图片描述
9、连接上面两个表,将median添加到对应的州位置上

df_state_vote_merge = df_state_vote.merge(state_median, on='state',how='left')
df_state_vote_merge

在这里插入图片描述
10、选出自己需要的列

df_state_final = df_state_vote_merge[['state','county','total_votes','BT','median_y']]
df_state_final

11、判断是否中位数与BT值,判定是否为拜登的城市,并添加到表中。

isBiden = df_state_final['BT']>df_state_final['median_y']
isBiden
df_state_final['isBiden'] = isBiden
df_state_final

在这里插入图片描述
终于终于做完了!!!每一道题的每一个小问花的时间都是以小时为单位。习题做出来了,有进步!虽然是用的笨方法,但是说明还有进步的空间啦!

最后的最后,今天是我生日哈哈,祝我自己生日快乐!
新的一年有新的成长!一切顺利,心想事成!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值