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

Python实现商业客户细分时报字符串类型减法不支持错误 寻求解决方案

错误根因

unsupported operand type(s) for -: 'str' and 'str'这个报错的原因很直接:你拿来做减法的两个值都是字符串类型,字符串本身不支持减法运算。顺着代码捋一共有3个问题,其中1个顺序问题会让代码根本跑不到你定位的聚合行就崩溃:

  • 执行顺序写反了:你在还没给df_fix赋值的时候就先写了df_fix["TotalSum"] = ...,运行到这行直接会报df_fix未定义的错
  • 日期列被你转成字符串了:处理InvoiceDate的时候你加了.dt.strftime('%Y-%m-%d'),这个方法是把时间对象格式化成字符串用的,转完之后pandas就不认这列是时间了,自然没法算时间差
  • 基准日期snapshot_date也是字符串:因为InvoiceDate整列都是字符串,取max得到的也是字符串,你再加个str()转出来的timedelta,拼完还是字符串,拿字符串减字符串肯定报错。
修复方法

改三个地方就行:

  1. 调整代码顺序:先采样拿到df_fix,再算TotalSum列
  2. 处理InvoiceDate的时候别转字符串,转成datetime类型就停,带时区的话直接把时区信息去掉即可,不用格式化成字符串
  3. 算snapshot_date的时候全程保持时间类型,别转字符串

修正后的可运行完整代码:

# Import The Libraries
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from datetime import timedelta

# Import The Dataset
df = pd.read_csv('path/data.csv', encoding='latin1')
df = df[df['CustomerID'].notna()]

# 先采样得到df_fix,再做后续列计算
df_fix = df.sample(10000, random_state = 42)
# Create TotalSum column
df_fix["TotalSum"] = df_fix["Quantity"] * df_fix["UnitPrice"]

# 转换InvoiceDate为datetime类型,移除时区信息,不要转字符串
df_fix["InvoiceDate"] = pd.to_datetime(df_fix["InvoiceDate"], errors='coerce', utc=True).dt.tz_localize(None)

# Create date variable that records recency,全程保持datetime类型
snapshot_date = df_fix["InvoiceDate"].max() + timedelta(days=1)

# Aggregate data by each customer
customers = df_fix.groupby(['CustomerID']).agg({
    'InvoiceDate': lambda x: (snapshot_date - x.max()).days ,
    'InvoiceNo': 'count',
    'TotalSum': 'sum'})

# 可选:按RFM模型惯例重命名列,方便后续分析
customers = customers.rename(columns={'InvoiceDate':'Recency', 'InvoiceNo':'Frequency', 'TotalSum':'Monetary'})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 23:03:24