针对dataframe指定列的值,得到新列的值

63 阅读2分钟
def df_row(row):
    if row["A"]=="00001111": 
        row["商场"]="m1" 
    elif row["A"]=="00002222": 
        row["商场"]="m2" 
    elif row["A"]=="00003333": 
        row["商场"]="m3" 
    elif row["A"]=="00004444": 
        row["商场"]="m4" 
    elif row["A"]=="00005555": 
        row["商场"]="m5" 
    else: row["商场"]="m6" 
        return row 
    df_1=df_1.apply(df_row) 
    df_2=df_2.apply(df_row)


在这个代码中,问题出在 DataFrame.apply() 方法的使用方式和对行的修改方式。以下是问题的详细分析和改进建议:

代码问题分析

  1. apply() 默认处理列而非行

    • apply() 默认沿着列(axis=0)应用函数,但你的 df_row 函数期望对每一行进行操作。因此需要明确指定 axis=1
    • 否则,df_row 会应用到每列,而不是每行,导致错误行为。
  2. 对行的修改问题

    • row["商场"] 的修改会报错或没有效果,因为 apply() 传递的 row 是行的副本,直接修改不会影响原 DataFrame
  3. 返回值的要求

    • apply() 函数期望 df_row 返回整个行,修改后的行会被用来更新原始 DataFrame
  4. 结果未赋值

    • df_1.apply(df_row) 的结果需要赋值回 df_1,否则修改不会生效。

改进后的代码

以下是修正后的代码:

def df_row(row):
    if row["A"] == "00001111":
        row["商场"] = "m1"
    elif row["A"] == "00002222":
        row["商场"] = "m2"
    elif row["A"] == "00003333":
        row["商场"] = "m3"
    elif row["A"] == "00004444":
        row["商场"] = "m4"
    elif row["A"] == "00005555":
        row["商场"] = "m5"
    else:
        row["商场"] = "m6"
    return row

# 应用到 df_1 和 df_2
df_1 = df_1.apply(df_row, axis=1)
df_2 = df_2.apply(df_row, axis=1)

更简洁的替代方案:使用 mapapply 更高效

如果映射关系是简单的一对一映射,可以使用字典和 map() 函数,这样会更加简洁和高效:

# 映射关系
mapping = {
    "00001111": "m1",
    "00002222": "m2",
    "00003333": "m3",
    "00004444": "m4",
    "00005555": "m5"
}

# 使用 map() 并添加默认值
df_1["商场"] = df_1["A"].map(mapping).fillna("m6")
df_2["商场"] = df_2["A"].map(mapping).fillna("m6")

总结

  1. 如果使用 apply(),确保设置 axis=1,并返回修改后的行。
  2. 推荐用字典和 map() 函数完成一对一映射任务,代码更简洁,性能更好。
  3. 验证代码是否生效,关键是检查最终的 DataFrame 是否更新了新列 商场 的值。