You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pandas根据Year列匹配对应人口列创建DataFrame新列

问题描述

这是我首次在Stack Overflow提问,若格式存在瑕疵还请谅解。
我在完成多个DataFrame拼接后,始终无法实现基于其他列(df["2013 Pop"]、df["2014 Pop"]等)的行值新建df["population"]列的需求:当事件发生在对应年份时,需要提取相同年份Pop列的对应人口值,填充到新的df["population"]列中。比如df["Year"] == 2014时,取df["2014 Pop"]的同行值填入新列。

我的DataFrame结构示例如下:

d = {
  "Year" : [2013,2014,2015...],
  "State" : ["Louisana", "Texas", "California"... ],
  "City" : ["New Orleans", "Dallas", "Sacramento"...],
  "Number Killed" : [4,6,2,4],
  "Safety Grade" : ["A", "B", "C", "D"...],
  "2013 Pop" : [421329, 232321, 2454543....],
  "2014 Pop" : [454545, 655654, 3421342....],
  "2015 Pop" : [142314, 454355, 4324323....],
  "Incident Date(datetime dtype)" : ["12-29-2014", "3-12-2017"...]
}
df = pd.DataFrame(d)

我尝试过mapping、loc、apply等方法均未成功,原本认为带条件判断的自定义函数思路可行,但运行时持续报错。我编写的函数和调用代码如下:

def categorise(row):
  if row["Year"] == 2014:
    return df["2014 Pop"]
  elif row["Year"] == 2015:
    return df["2015 Pop"]
  elif row["Year"] == 2016:
    return df["2016 Pop"]
  elif row["Year"] == 2017:
    return df["2017 Pop"]
  else:
    return "NONE"

df["Population"] = df.apply(lambda row : categorise(row), axis = 1)

执行后抛出错误:ValueError: Wrong number of items passed 3609 (length of the df), placement implies 1

报错原因

核心问题出在自定义函数的返回值:apply(axis=1)是逐行遍历操作,每次传入的row是当前行的Series对象,你返回的是整个DataFrame的整列数据(比如df["2014 Pop"]长度为3609,等于整个表的行数),而非当前行对应的单个数值,pandas无法将长度为3609的序列填入单个单元格,因此抛出长度不匹配错误。

实现方案

方案1:numpy.select 向量化实现(优先推荐)

使用numpy的条件选择函数做向量化匹配,不需要逐行遍历,运行效率比apply高数十倍,适合大体量数据:

import numpy as np

# 按顺序写匹配条件、对应返回的列
conditions = [
    df["Year"] == 2013,
    df["Year"] == 2014,
    df["Year"] == 2015,
    df["Year"] == 2016,
    df["Year"] == 2017
]
pop_cols = [
    df["2013 Pop"],
    df["2014 Pop"],
    df["2015 Pop"],
    df["2016 Pop"],
    df["2017 Pop"]
]

# 匹配到对应条件就取对应列的同行值,未匹配到则返回"NONE"
df["Population"] = np.select(conditions, pop_cols, default="NONE")

方案2:修正原有apply自定义函数

如果习惯使用apply写法,只需要把函数中返回整列的写法改为返回当前行的对应值即可,同时可以去掉多余的lambda嵌套:

def categorise(row):
  if row["Year"] == 2014:
    return row["2014 Pop"] # 注意这里取当前row的对应值,不是全局df的整列
  elif row["Year"] == 2015:
    return row["2015 Pop"]
  elif row["Year"] == 2016:
    return row["2016 Pop"]
  elif row["Year"] == 2017:
    return row["2017 Pop"]
  else:
    return "NONE"

# 直接传入函数对象即可,不需要套lambda
df["Population"] = df.apply(categorise, axis=1)

方案3:动态列名匹配(适合年份较多的场景)

如果涉及的年份范围很大,逐个写if判断代码冗余度高,可以直接通过行内的Year值拼接列名,动态取对应值:

df["Population"] = df.apply(
    lambda row: row.get(f"{int(row['Year'])} Pop", "NONE"),
    axis=1
)

内容的提问来源于stack exchange,提问作者Nickguild1993

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.01 00:27:23