Pandas技术问题:如何筛选人口总和刚超220万的马德里城市子集?
问题分析与解决方案
咱们先理清你遇到的问题:你写的madrid[madrid['Población(2017)'].sum() > 2178000]逻辑有误——这个表达式先计算了整列的人口总和,得到一个单一的布尔值(比如True),然后你试图用这个布尔值去索引DataFrame的行,但DataFrame的行索引并不是布尔值,所以才会抛出KeyError: True的错误。
你的核心需求是筛选一组城市,让它们的人口总和刚超过220万(看你代码里写的是2178000,可根据实际目标调整),正确的思路应该是先按人口从多到少排序,再逐步累加人口,找到第一个累加和超过目标值的节点,最后取出对应的城市集合。
具体实现代码
import pandas as pd from unicodedata import normalize # 读取并预处理数据(保留你的原有代码) df = pd.read_html('https://es.wikipedia.org/wiki/Anexo:Municipios_de_la_Comunidad_de_Madrid') madrid = df[0] madrid['Población(2017)'] = madrid['Población(2017)'].apply(lambda x:normalize('NFKD', x)).str.replace(' ','') madrid['Población(2017)'] = pd.to_numeric(madrid['Población(2017)']) # 1. 按人口降序排序,优先选择人口多的城市(最快达到目标总和) madrid_sorted = madrid.sort_values('Población(2017)', ascending=False) # 2. 计算累计人口和,直观看到每一步的总和变化 madrid_sorted['累计人口'] = madrid_sorted['Población(2017)'].cumsum() # 3. 设定目标值,找到首次超过目标的城市位置 目标人口 = 2200000 # 可替换为你需要的2178000 # 获取第一个累计人口超过目标的行索引 首次超过索引 = madrid_sorted[madrid_sorted['累计人口'] > 目标人口].index[0] # 4. 筛选出从第一个城市到该索引的所有城市 选中的城市 = madrid_sorted.loc[:首次超过索引] # 查看结果 print("选中城市的人口总和:", 选中的城市['Población(2017)'].sum()) print(选中的城市[['Municipio', 'Población(2017)', '累计人口']])
代码逻辑说明
- 降序排序:优先选人口多的城市,能以最少的城市数量达到目标总和,这是最符合"刚超过"需求的常规解法。
- 累计人口计算:通过
cumsum()生成每行的累计人口,方便我们追踪总和的动态变化。 - 定位节点:用布尔索引找到第一个累计人口超过目标的行,取到该行的所有城市,就能得到总和刚超过目标的最小城市集合。
补充提示
如果你想要的是所有可能的城市组合中总和刚超过220万,那这属于子集和问题,实现起来会复杂很多(需要回溯或动态规划),但通常这类需求都是指向"用最少城市数量达到目标",上面的代码完全可以满足这个场景。
内容的提问来源于stack exchange,提问作者Juan Luis Chulilla
相关产品推荐
相关产品推荐

