使用ThreadPoolExecutor获取数据后,如何正确将列表作为行添加至DataFrame?
问题:yfinance多线程获取股票数据后DataFrame格式异常
原代码
#!/usr/bin/env python import sys import yfinance as yf from concurrent.futures import ThreadPoolExecutor import pandas as pd def get_stats(ticker): info = yf.Tickers(ticker).tickers[ticker].info data = [ticker, info['volume']/info['floatShares'], info['floatShares']] return data ticker_list = sys.argv[1:] ticker_list = ['AAPL', 'AMZN', 'GOOG'] ticker_list = [item.upper() for item in ticker_list] table_title = ['Symbol', 'FTR', 'Float'] df = pd.DataFrame(columns = table_title) with ThreadPoolExecutor() as executor: results = list(executor.map(get_stats, ticker_list)) df.loc[len(df)] = results print(df)
实际输出
Symbol FTR Float 0 [AAPL, 0.003960062654206358, 15179506298] [AMZN, 0.006952834770567285, 9360261411] [GOOG, 0.0029524428963116282, 10942799280]
期望输出
Symbol FTR Float 0 AAPL 0.003960062654206358 15179506298 1 AMZN 0.006952834770567285 9360261411 2 GOOG 0.002952442896311628 10942799280
问题原因
df.loc[len(df)] = results 是将整个results列表(包含3个股票的子列表)作为一行数据赋值给DataFrame,导致每个列都被填充了一个完整的子列表,而非将每个子列表作为单独的一行。
修正方案
直接用results二维列表构造DataFrame,无需先创建空DataFrame再逐行添加:
#!/usr/bin/env python import sys import yfinance as yf from concurrent.futures import ThreadPoolExecutor import pandas as pd def get_stats(ticker): info = yf.Tickers(ticker).tickers[ticker].info data = [ticker, info['volume']/info['floatShares'], info['floatShares']] return data ticker_list = sys.argv[1:] ticker_list = ['AAPL', 'AMZN', 'GOOG'] ticker_list = [item.upper() for item in ticker_list] table_title = ['Symbol', 'FTR', 'Float'] with ThreadPoolExecutor() as executor: results = list(executor.map(get_stats, ticker_list)) # 直接用results构造DataFrame,每个子列表对应一行 df = pd.DataFrame(results, columns=table_title) print(df)
补充说明
如果需要保留逐行添加的逻辑(比如需要处理中间数据),可以循环遍历results逐个添加:
df = pd.DataFrame(columns = table_title) with ThreadPoolExecutor() as executor: results = list(executor.map(get_stats, ticker_list)) for row in results: df.loc[len(df)] = row
内容的提问来源于stack exchange,提问作者Tex
相关产品推荐
相关产品推荐

