跳至主要內容
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?

4563博客

全新的繁體中文 WordPress 網站
  • 首頁
  • pandas 花了 7 分 32 秒生成一张[45639 rows x 7 columns]的表,实在是太太太慢了,求更快的方法
未分類
7 2 月 2021

pandas 花了 7 分 32 秒生成一张[45639 rows x 7 columns]的表,实在是太太太慢了,求更快的方法

pandas 花了 7 分 32 秒生成一张[45639 rows x 7 columns]的表,实在是太太太慢了,求更快的方法

資深大佬 : yaleyu 3

原始数据结构如下,总共 7000 多条,想扁平化然后放到 pd 里面做进一步的处理

>>> len(funds) 7597 >>> funds[0] {'000005': {'company': '嘉实', 'name': '嘉实增强信用定期债券', 'type': '定开债券', 'earning': {'1m': 0.1, '3m': 1.0, '6m': 0.85, '1y': 2.59}, 'hold_stocks': [{'code': '601966', 'name': '玲珑轮胎', 'percentage': '0.51%', 'volume': 0.67, 'value': 23.48}, {'code': '002745', 'name': '木林森', 'percentage': '0.47%', 'volume': 1.5, 'value': 21.92}]}} >>> funds[-1] {'970008': {'company': '华安', 'name': '华安证券汇赢增利一年持有混合 C', 'type': '混合型', 'earning': {'1m': -0.55, '3m': -0.58, '6m': 0.67, '1y': 0}, 'hold_stocks': [{'code': '300692', 'name': '中环环保', 'percentage': '0.72%', 'volume': 31.81, 'value': 496.79}, {'code': '603012', 'name': '创力集团', 'percentage': '0.67%', 'volume': 72.28, 'value': 465.48}, {'code': '300197', 'name': '铁汉生态', 'percentage': '0.64%', 'volume': 138.93, 'value': 440.39}, {'code': '002562', 'name': '兄弟科技', 'percentage': '0.23%', 'volume': 31.0, 'value': 160.27}]}} >>> 

生成 df 代码如下:

df = pd.DataFrame(columns=['fund_code', 'fund_company', 'stock_code', 'stock_name', 'stock_percentage', 'stock_volume', 'stock_value']) i = 0 for fund in funds:     fund_code = list(fund.keys())[0]     fund_company = list(fund.values())[0]['company']     if list(fund.values())[0]['hold_stocks']:         for hold_stock in list(fund.values())[0]['hold_stocks']:             stock_code = hold_stock['code'].strip()             stock_name = hold_stock['name'].strip()             stock_percentage = float(hold_stock['percentage'].strip('%'))             stock_volume = hold_stock['volume']             stock_value = hold_stock['value']             df.loc[i] = [fund_code, fund_company, stock_code, stock_name, stock_percentage, stock_volume, stock_value]             i += 1     else:         df.loc[i] = [fund_code, fund_company, '', '', 0, 0, 0]  # 不持仓任何股票则仅记录基金代码和基金公司         i += 1 

大佬有話說 (19)

  • 資深大佬 : bigtan

    pd.Dataframe.from_dict

  • 資深大佬 : bigtan

    你不是生成了一张表,而是几万张

  • 資深大佬 : binux

    一次把数据喂给 dataframe

  • 資深大佬 : lv2016

    直接修改 dataframe 确实很慢,建议先生成 list,再转 dataframe

  • 資深大佬 : WinG

    量化炒股???

  • 主 資深大佬 : yaleyu

    @lv2016 试过先扁平化 dict 成 list,再赋值给 df,时间稍晚缩短了一丢丢,不过不是很明显。

  • 主 資深大佬 : yaleyu

    @bigtan 谢谢,我研究一下这个,新年快乐哈。

  • 資深大佬 : princelai

    上说了,每次操作 df 是很慢的,可以操作 json 变为适合的格式,然后一次性给 pandas

    “`
    from pandas import json_normalize

    funds = [{‘000005’: {‘company’: ‘嘉实’, ‘name’: ‘嘉实增强信用定期债券’, ‘type’: ‘定开债券’, ‘earning’: {‘1m’: 0.1, ‘3m’: 1.0, ‘6m’: 0.85, ‘1y’: 2.59},
    ‘hold_stocks’: [{‘code’: ‘601966’, ‘name’: ‘玲珑轮胎’, ‘percentage’: ‘0.51%’, ‘volume’: 0.67, ‘value’: 23.48},
    {‘code’: ‘002745’, ‘name’: ‘木林森’, ‘percentage’: ‘0.47%’, ‘volume’: 1.5, ‘value’: 21.92}]}},
    {‘970008’: {‘company’: ‘华安’, ‘name’: ‘华安证券汇赢增利一年持有混合 C’, ‘type’: ‘混合型’, ‘earning’: {‘1m’: -0.55, ‘3m’: -0.58, ‘6m’: 0.67, ‘1y’: 0},
    ‘hold_stocks’: [{‘code’: ‘300692’, ‘name’: ‘中环环保’, ‘percentage’: ‘0.72%’, ‘volume’: 31.81, ‘value’: 496.79},
    {‘code’: ‘603012’, ‘name’: ‘创力集团’, ‘percentage’: ‘0.67%’, ‘volume’: 72.28, ‘value’: 465.48},
    {‘code’: ‘300197’, ‘name’: ‘铁汉生态’, ‘percentage’: ‘0.64%’, ‘volume’: 138.93, ‘value’: 440.39},
    {‘code’: ‘002562’, ‘name’: ‘兄弟科技’, ‘percentage’: ‘0.23%’, ‘volume’: 31.0, ‘value’: 160.27}]}}]

    new_funds = []
    for fund in funds:
    for k, v in fund.items():
    v.update({‘code’: k})
    new_funds.append(v)
    df = json_normalize(new_funds, ‘hold_stocks’, [‘company’, ‘name’, ‘type’, ‘code’], meta_prefix=’fund_’, record_prefix=’stock_’)

    “`

  • 資深大佬 : princelai

    缩进乱了,new_funds.append 是在两层循环里,json_normalize 是在最外层,循环完毕才去执行的

  • 資深大佬 : Escapist367

    df_list=[]
    i = 0
    for fund in funds:
    fund_code = list(fund.keys())[0]
    fund_company = list(fund.values())[0][‘company’]
    if list(fund.values())[0][‘hold_stocks’]:
    for hold_stock in list(fund.values())[0][‘hold_stocks’]:
    stock_code = hold_stock[‘code’].strip()
    stock_name = hold_stock[‘name’].strip()
    stock_percentage = float(hold_stock[‘percentage’].strip(‘%’))
    stock_volume = hold_stock[‘volume’]
    stock_value = hold_stock[‘value’]
    df_list.append([fund_code, fund_company, stock_code, stock_name, stock_percentage, stock_volume, stock_value])
    i += 1
    else:
    df_list.append([fund_code, fund_company, ”, ”, 0, 0, 0]) # 不持仓任何股票则仅记录基金代码和基金公司
    i += 1

    df = pd.DataFrame(df_list,columns=[‘fund_code’, ‘fund_company’, ‘stock_code’, ‘stock_name’, ‘stock_percentage’, ‘stock_volume’, ‘stock_value’])

    ==================
    在你基础上最小改动。
    你先用一个 list 存放每行结果,再一次性转 df 就行了,大概只要 1s

  • 主 資深大佬 : yaleyu

    @princelai 缩进乱了没事,好像 V2 回复不能用 markdown 格式。

    你这个太牛了,时间从 7 分多钟缩短到 0.5 秒了,不过数据从 45639 行减少成了 42138 行,我再仔细检查一下哪些数据被抛弃了。

    新年快乐哈。

  • 資深大佬 : billgreen1

    @princelai 这个赞,我之前都不了解这个函数

  • 資深大佬 : youthfire

    pandas 速度还是很快的,我的经验是基本上百万级的,论分钟的话多半是嵌套写错了在低效执行。数据库处理的话优势更明显。

  • 資深大佬 : winglight2016

    你用了两层 for 然后调用 loc 方法,当然会慢呀。记得减少 for 循环次数以及 loc 调用次数。

    pandas 的优势在 dataframe 的批处理上,尽量把计算操作放到 dataframe/series 的原生方法里进行,大部分需求应该都能满足。

  • 資深大佬 : lixuda

    pandas 不要用 for,用 apply 。

  • 資深大佬 : allAboutDbmss

    https://github.com/modin-project/modin
    我每天都向人推荐这个

  • 資深大佬 : owenliang

    学学 pyspark 。

  • 資深大佬 : fxrocks

    1 正解

  • 資深大佬 : volvo007

    还有个函数
    pd.json_normalize,可以把半结构化的 json (比如数组套对象又套数组而且不同组嵌套不一样的)转为字典,而且可以有选择性地抽取 json 中的某些字段
    贼好用

文章導覽

上一篇文章
下一篇文章

AD

其他操作

  • 登入
  • 訂閱網站內容的資訊提供
  • 訂閱留言的資訊提供
  • WordPress.org 台灣繁體中文

51la

4563博客

全新的繁體中文 WordPress 網站
返回頂端
本站採用 WordPress 建置 | 佈景主題採用 GretaThemes 所設計的 Memory
4563博客
  • Hostloc 空間訪問刷分
  • 售賣場
  • 廣告位
  • 賣站?
在這裡新增小工具