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

如何对pandas DataFrame列内元素做环比除法并取自然对数?

问题描述

我被这段代码难住了。我有如下简单的DataFrame:

Business Date   dic-22  gen-23  feb-23
03/10/2022   112,0   121,1   131,2 
04/10/2022   87,0    103,0   122,5 
05/10/2022   114,3   102,8   99,6 
06/10/2022   101,7   116,6   104,3 
07/10/2022   116,6   103,7   110,8 
10/10/2022   108,8   107,3   112,0 

我需要对每一列中的每个值与其前一个值做除法运算,例如dic-22列依次计算87/112、114/87……,最终得到如下结果:

Business Date   dic-22  gen-23  feb-23
03/10/2022  0   0   0
04/10/2022   0,8     0,9     0,9   
05/10/2022   1,3     1,0     0,8   
06/10/2022   0,9     1,1     1,0   
07/10/2022   1,1     0,9     1,1   
10/10/2022   0,9     1,0     1,0   

之后我还需要对这些结果取自然对数。我尝试实现但卡在了第一步(列内除法计算),以下代码无法正常运行:

for i, column in df.items():
    for j, row in df.iterrows():
       # if j > 0:  # Skip first row
            df.iloc[:, 1:] = df.iloc[:, 1:] / df.iloc[:, 1:].shift()
解决方法

你的代码问题在于:

  • 嵌套循环完全多余,pandas的矢量化操作可以直接处理列运算
  • 原数据中的数值用逗号作为小数点分隔,属于字符串类型,无法直接进行除法计算
  • 直接赋值会覆盖原DataFrame的原始数据

按以下步骤处理即可:

步骤1:转换数值格式

先把数值列的逗号替换为点,再转换成浮点数类型:

import pandas as pd
import numpy as np

# 假设你的DataFrame已加载,先定义数值列
numeric_cols = ['dic-22', 'gen-23', 'feb-23']
# 替换逗号为点并转成float
df[numeric_cols] = df[numeric_cols].apply(lambda x: x.str.replace(',', '.').astype(float))

步骤2:计算列内环比比值

用shift()方法获取前一行数据,直接做除法运算,无需循环:

# 计算当前值与前一行值的比值
ratio_df = df[numeric_cols].div(df[numeric_cols].shift(1))
# 第一行没有前一行数据,替换为0
ratio_df.iloc[0] = 0

步骤3:生成示例格式的结果

合并日期列,并将小数点转回逗号以匹配示例格式:

# 合并日期列和比值列
result_df = pd.concat([df['Business Date'], ratio_df], axis=1)
# 保留1位小数,再把点替换为逗号
result_df[numeric_cols] = result_df[numeric_cols].round(1).astype(str).str.replace('.', ',')

步骤4:对结果取自然对数

注意第一行的0无法取对数,需单独处理:

# 先把字符串转回数值类型
log_df = result_df[numeric_cols].replace(',', '.', regex=True).astype(float)
# 对非0值取自然对数,0保持不变
log_df = log_df.apply(lambda x: np.where(x == 0, 0, np.log(x)))
# 合并日期列得到最终对数结果
final_log_df = pd.concat([df['Business Date'], log_df], axis=1)

完整可运行代码

import pandas as pd
import numpy as np

# 构造你的DataFrame(模拟读取后的数据)
data = {
    'Business Date': ['03/10/2022', '04/10/2022', '05/10/2022', '06/10/2022', '07/10/2022', '10/10/2022'],
    'dic-22': ['112,0', '87,0', '114,3', '101,7', '116,6', '108,8'],
    'gen-23': ['121,1', '103,0', '102,8', '116,6', '103,7', '107,3'],
    'feb-23': ['131,2', '122,5', '99,6', '104,3', '110,8', '112,0']
}
df = pd.DataFrame(data)

# 步骤1:转换数值格式
numeric_cols = ['dic-22', 'gen-23', 'feb-23']
df[numeric_cols] = df[numeric_cols].apply(lambda x: x.str.replace(',', '.').astype(float))

# 步骤2:计算环比比值
ratio_df = df[numeric_cols].div(df[numeric_cols].shift(1))
ratio_df.iloc[0] = 0

# 步骤3:生成示例格式结果
result_df = pd.concat([df['Business Date'], ratio_df], axis=1)
result_df[numeric_cols] = result_df[numeric_cols].round(1).astype(str).str.replace('.', ',')
print("比值结果:")
print(result_df)

# 步骤4:取自然对数
log_df = result_df[numeric_cols].replace(',', '.', regex=True).astype(float)
log_df = log_df.apply(lambda x: np.where(x == 0, 0, np.log(x)))
final_log_df = pd.concat([df['Business Date'], log_df], axis=1)
print("\n对数结果:")
print(final_log_df)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 06:15:35