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

pandasql传入DataFrame表名参数报错UFuncTypeError的解决咨询

问题分析与解决:pandasql传入DataFrame参数报错

问题背景

处理名为movies的DataFrame,genres列以逗号分隔多类型标签。原函数通过pandasql统计各类型电影数量可正常运行,但新增table参数支持数据子集分析后,调用时出现错误:

UFuncTypeError: ufunc 'add' did not contain a loop with signature matching types (dtype('<U37'), dtype('<U37')) -> dtype('<U37')

原正常代码:

from pandasql import sqldf
pysqldf = lambda q: sqldf(q, globals())

def number_in_genre(genres_list):
    dataframes = []
    for genre in genres_list:
        q = """SELECT COUNT(*) 
               FROM movies 
               WHERE genres LIKE '%""" + genre + """%'"""
        df = pysqldf(q)
        df['genre'] = genre
        dataframes.append(df)
    return pd.concat(dataframes)

修改后报错代码:

def number_in_genre(genres_list, table):
    dataframes = []
    for genre in genres_list:
        q = """SELECT COUNT(*) 
               FROM """ + table + """ 
               WHERE genres LIKE '%""" + genre + """%'"""
        df = pysqldf(q)
        df['genre'] = genre
        dataframes.append(df)
    return pd.concat(dataframes)

错误原因

原函数中FROM后是字符串'movies',pysqldf通过globals()找到全局变量里对应的movies DataFrame。但修改后传入的table参数是DataFrame对象,而非字符串表名,直接将字符串与DataFrame对象拼接时,Python会尝试执行对象间的加法操作,而DataFrame不支持与字符串直接相加,因此触发了numpy的ufunc类型不匹配错误。

解决思路

方案1:将DataFrame注册为临时表名传入

通过给传入的DataFrame分配一个临时变量名,注册到全局命名空间,让pandasql能识别该表名:

from pandasql import sqldf
import pandas as pd

pysqldf = lambda q: sqldf(q, globals())

def number_in_genre(genres_list, table):
    # 创建临时表名并注册到全局空间
    temp_table = "_temp_movie_subset"
    globals()[temp_table] = table
    dataframes = []
    for genre in genres_list:
        # 使用f-string拼接SQL,更简洁安全
        q = f"""SELECT COUNT(*) 
               FROM {temp_table} 
               WHERE genres LIKE '%{genre}%'"""
        df = pysqldf(q)
        df['genre'] = genre
        dataframes.append(df)
    # 清理临时变量,避免污染全局空间
    del globals()[temp_table]
    return pd.concat(dataframes)

调用示例:

# 统计前30条数据中各类型数量
number_in_genre(["Horror", "Comedy"], movies.head(30))
# 统计低成本电影中各类型数量
low_budget_movies = movies.loc[movies['production_budget'] < 2000000]
number_in_genre(["Drama", "Action"], low_budget_movies)

方案2:传入表名字符串并确保DataFrame在命名空间中

如果不想用临时表,可将DataFrame赋值给一个变量,传入变量名字符串:

def number_in_genre(genres_list, table_name):
    dataframes = []
    for genre in genres_list:
        q = f"""SELECT COUNT(*) 
               FROM {table_name} 
               WHERE genres LIKE '%{genre}%'"""
        df = pysqldf(q)
        df['genre'] = genre
        dataframes.append(df)
    return pd.concat(dataframes)

调用示例:

low_budget_movies = movies.loc[movies['production_budget'] < 2000000]
number_in_genre(["Drama", "Action"], "low_budget_movies")

额外优化:避免SQL注入风险(可选)

如果genres_list来自外部输入,直接拼接字符串可能存在SQL注入风险,可改用参数化查询:

def number_in_genre(genres_list, table):
    temp_table = "_temp_movie_subset"
    globals()[temp_table] = table
    dataframes = []
    for genre in genres_list:
        # 使用?作为占位符,传入参数
        q = f"""SELECT COUNT(*) 
               FROM {temp_table} 
               WHERE genres LIKE ?"""
        # 拼接通配符后作为参数传入
        df = pysqldf(q, params=(f'%{genre}%',))
        df['genre'] = genre
        dataframes.append(df)
    del globals()[temp_table]
    return pd.concat(dataframes)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 19:09:55