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

Python中如何逐行更新DataFrame期权字段而非整列?

问题描述

我是一名自学的业余开发者,近期在处理期权数据时遇到难题:使用for循环解析期权合约信息时逻辑正常,但尝试为Pandas DataFrame添加contract_date、contract_type、strike_price三个字段时,循环会将整列更新为同一值,而非每行对应不同的正确值。我尝试了append、concat等多种方法,要么结果依旧错误,要么出现报错,请问正确的逐行更新DataFrame的方式是什么?

原代码

from numpy import dtype
import pandas as pd
import requests
import urllib.parse
from datetime import datetime
from dateutil import tz
 
s = requests.Session()


headers = {       #match headers on API request
        'Accept':'*',
        'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36'
        }
    #print('Enter a Ticker to Pull Data From')
    #ticker = input()
ticker = 'SPY'

tickerurl = f'https://cdn.cboe.com/api/global/delayed_quotes/options/{ticker}.json'
data = s.get(tickerurl).json()

lookupdata = data['data']['options']
df = pd.json_normalize(data['data']['options'])
df['ticker'] = ticker
  
for contract in lookupdata:
    y = contract['option'].replace(ticker,'')
    contract_date = f'20{y[0:2]}-{y[2:4]}-{y[4:6]}'
    z = y.replace(y[0:6],'')
    contract_type = "Call" if z[0] == 'C' else "Put"
    strikeprice = z.replace(z[0],'')
    strike_price = float(strikeprice)/1000
    df['contract_date'] = contract_date
    df['contract_type'] = contract_type
    df['strike_price'] = strike_price
 
print(df)

尝试的错误代码

from numpy import dtype
import pandas as pd
import requests
import urllib.parse
from datetime import datetime
from dateutil import tz
     
s = requests.Session()


headers = {       #match headers on API request
        'Accept':'*',
        'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36'
        }
    #print('Enter a Ticker to Pull Data From')
    #ticker = input()
ticker = 'SPY'

tickerurl = f'https://cdn.cboe.com/api/global/delayed_quotes/options/{ticker}.json'
data = s.get(tickerurl).json()

lookupdata = data['data']['options']
df = pd.json_normalize(data['data']['options'])
df['ticker'] = ticker
df2 = pd.DataFrame()  
for contract in lookupdata:
    y = contract['option'].replace(ticker,'')
    contract_date = f'20{y[0:2]}-{y[2:4]}-{y[4:6]}'
    z = y.replace(y[0:6],'')
    contract_type = "Call" if z[0] == 'C' else "Put"
    strikeprice = z.replace(z[0],'')
    strike_price = float(strikeprice)/1000
    df['contract_date'] = contract_date
    df['contract_type'] = contract_type
    df['strike_price'] = strike_price
    df2 = df.append(df2) 

print(df2)

# tried the following as well:

#    df2.append(df)
#df2 = pd.concat(df2)
#print(df2)

# gives the error TypeError: first argument must be an iterable of pandas objects, you passed an object of type "DataFrame"


    #trying the following gives a key error on contract_date
    
    #    df2.append(df)
    #    df2 = pd.concat(df2['contract_date']['contract_type'][strike_price])
    #print(df2)

#   df2.append(df)
#    df2 = #pd.concat((df2['contract_date'],df2['contract_type'],df2['strike_price']), #ignore_index=True)
#print(df2)

解决方案

错误根源

原代码中df['contract_date'] = contract_date这类写法是将整列赋值为当前循环的单个值,循环结束后整列只会保留最后一个合约的计算结果;而错误代码里的append/concat用法完全偏离需求,要么重复追加错误的整列数据,要么因参数格式错误报错。

正确写法1:生成列表批量赋值

先通过循环收集每行的计算结果到列表,再一次性赋值给DataFrame,效率高且逻辑清晰:

from numpy import dtype
import pandas as pd
import requests
import urllib.parse
from datetime import datetime
from dateutil import tz
 
s = requests.Session()

headers = {
        'Accept':'*',
        'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36'
        }

ticker = 'SPY'
tickerurl = f'https://cdn.cboe.com/api/global/delayed_quotes/options/{ticker}.json'
data = s.get(tickerurl).json()

lookupdata = data['data']['options']
df = pd.json_normalize(data['data']['options'])
df['ticker'] = ticker

# 初始化空列表存储每行结果
contract_dates = []
contract_types = []
strike_prices = []

for contract in lookupdata:
    y = contract['option'].replace(ticker,'')
    contract_date = f'20{y[0:2]}-{y[2:4]}-{y[4:6]}'
    z = y.replace(y[0:6],'')
    contract_type = "Call" if z[0] == 'C' else "Put"
    strikeprice = z.replace(z[0],'')
    strike_price = float(strikeprice)/1000
    
    # 将当前合约结果追加到对应列表
    contract_dates.append(contract_date)
    contract_types.append(contract_type)
    strike_prices.append(strike_price)

# 批量赋值给DataFrame的列
df['contract_date'] = contract_dates
df['contract_type'] = contract_types
df['strike_price'] = strike_prices

print(df)

正确写法2:使用apply函数(更简洁)

利用Pandas的apply方法对每行数据进行解析,避免显式循环:

from numpy import dtype
import pandas as pd
import requests
import urllib.parse
from datetime import datetime
from dateutil import tz
 
s = requests.Session()

headers = {
        'Accept':'*',
        'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36'
        }

ticker = 'SPY'
tickerurl = f'https://cdn.cboe.com/api/global/delayed_quotes/options/{ticker}.json'
data = s.get(tickerurl).json()

df = pd.json_normalize(data['data']['options'])
df['ticker'] = ticker

# 定义解析单个期权合约的函数
def parse_option(row):
    option_str = row['option'].replace(ticker, '')
    # 解析合约日期
    contract_date = f'20{option_str[0:2]}-{option_str[2:4]}-{option_str[4:6]}'
    # 解析合约类型和行权价
    rest = option_str[6:]
    contract_type = "Call" if rest[0] == 'C' else "Put"
    strike_price = float(rest[1:])/1000
    return pd.Series([contract_date, contract_type, strike_price], 
                     index=['contract_date', 'contract_type', 'strike_price'])

# 应用函数并合并到原DataFrame
df = pd.concat([df, df.apply(parse_option, axis=1)], axis=1)

print(df)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 12:24:46