Python: 拆分文件讓百萬級數據運行速度提高135倍

2021-02-20 Stata連享會

作者:許夢潔 (中山大學)

Email: StataChina@163.com

Stata連享會 計量專題  || 公眾號合集

點擊查看完整推文列表

(西安, 3月26-29日,司繼春-遊萬海 主講;  內附助教招聘)

連享會-文本分析與爬蟲專題班,西北工業大學,2020.3.26-29

語言:Python
方法:拆分文件
目的:提高運行速度

一、任務描述

對 2010 年後 49083 條上市公司股權變更數據(Firm-Event 觀測)分別統計每個事件發生前後 15 天公司:

二、數據描述數據集總樣本數2010年後的樣本數上市公司股權變更記錄5758449083上市公司公告記錄27870262758934上市公司日超額收益97494645534947

三、解決思路

在Python 構造一個類似於 Excel 中的 countif 函數即可。具體見我上一篇博文 [百萬級大樣本中的 countif 實現]。

特別說明: 文中包含的連結在微信中無法生效。請點擊本文底部左下角的【閱讀原文】。

四、潛在問題

雖然按照上一篇文章的思路也能基本完成任務,但是程序運行非常慢,光跑一次統計窗口期公告數據的程序就要27個小時,所以必須優化程序以提高運行速度。

五、優化思路

由於全樣本非常大,上篇博文的程序相當於是對每一個公司股東股權變動事件在全部的公告池(2758934條記錄)中進行搜索,顯然這樣做是無效率的。

因此,此次程序優化的主要思路是分別拆分 49083 條公司股東股權變動事件和 2758934 條上市公司公告記錄,並將兩類拆分的文件對應起來。舉個例子:

第一步: 將股票代碼在 000001 到 000049 的公司股權變動事件拆出來第二步: 將股票代碼在000001 到 000049 的公司公告拆出來形成一個小的公告搜索池,然後對這部分公司的股權事件在這個小搜索池裡統計公告記錄。

通過拆分文件得到的精確匹配大大減小了每一個事件的搜索範圍,可以大幅提高程序運行效率。優化後跑一次同樣的統計窗口期公告數據程序僅需 12 分鐘,是原來運行速度的 135 倍。

六、核心代碼(以統計窗口期 CAR 為例)1. 初步拆分

為了保證運行效率最高,首先平均分拆 CAR 序列,遍歷股票日超額收益序列數據,設定閾值為 50000,每 50000 條數據拆出一個文件,以 "CAR+編號" 為文件名 (eg: CAR109.txt)。最後共拆出了 110 個文件,Python 代碼如下:

LIMIT = 50000
file_count = 0
url_list = []

with open("股票日超額收益序列.txt") as f:
for line in f:
url_list.append(line)
if len(url_list)<LIMIT:
continue
file_name = str(file_count)+".txt"
with open(file_name,'w') as file:
for url in url_list[:-1]:
file.write(url)
file.write(url_list[-1].strip())
url_list = []
file_count += 1

2. 根據分拆文件記錄拆分股票節點

遍歷拆出來的 110 個 CAR 文件,分別記錄每個文件最後一個觀測的股票代碼,並逐條寫入 「拆分節點.txt」 中。Python 代碼如下:

import pandas as pd

for i in range(111):
file = "CAR"+repr(i)+".txt"
data = pd.read_table(file, header=None, encoding='utf-8', delim_whitespace=True)
data.columns = ['stkcd', '日期序列', '日超額收益']
stkcdlist = data.loc[:,'stkcd']
end = str(stkcdlist[len(stkcdlist)-1])
with open("拆分節點.txt",'a') as f:
f.write(end+"\n")
print(end)
f.close()

3. 根據拆分節點拆分事件列表並再拆分 CAR 列表

由於初步拆分是根據樣本數拆分,因此出現了同一隻股票不同日期的 CAR 會被拆到兩個不同文件的情況,十分不利於後面股權變更文件與 CAR 文件拆分後實現完美匹配。

因此,需要根據第二步得到拆分節點處的股票代碼對 CAR 列表再拆分,並同時拆分股權變更列表。經過這一步後拆分後的兩種文件就可以實現精確匹配。

此外,由於事先已經對股權變更文件以及 CAR 文件根據股票代碼以及日期進行排過序,因此接下來的拆分只需逐行遍歷,判斷遍歷到的觀測股票代碼與拆分節點處的股票代碼的關係,如果遍歷處股票代碼大於當前拆分節點,則保存一個分拆文件,清空相關變量並開啟下一個分拆文件。Python 代碼如下:

import pandas as pd

dataf = pd.read_table("拆分節點.txt",header=None,encoding='utf-8',delim_whitespace=True)
dataf.columns = ['節點']

LIMIT = dataf.loc[:,'節點']
file_count = 0
url_list = []
line_count = 0


with open("股票日超額收益序列.txt") as f:
for line in f:
url_list.append(line)
line_count += 1
currentstkcd = int(line.split("\t")[0])
print(currentstkcd)
try:
print(LIMIT[file_count])
if (currentstkcd < LIMIT[file_count]):
continue
except:
print("已經是最後一個觀測")
file_name = "CAR"+str(file_count)+".txt"
print(file_name)
with open(file_name,'w') as file:
try:
file.write(left)
except:
pass
for url in url_list[:-1]:
file.write(url)
left = url_list[-1]
url_list = []
file_count += 1

4. 基於拆分後的事件列表和日期序列統計數據

一一對應地拆完大文件之後就可以在縮小的搜索範圍裡 countif 啦,這部分思路見上一篇博文百萬級大樣本中的countif實現 (點擊底部【閱讀原文】查看連結)。跑完49083 條數據的結果只需要 12 分鐘,簡直是飛一般的感覺(`・ω・´)。

import pandas as pd
from datetime import *

timespan = timedelta(days=1)

def getlist(add):
data = pd.read_table(add,encoding='utf-8',delim_whitespace=True)
data.columns=['stkcd','日期序列','日超額收益']
return(data)

def 區間計數(股票代碼,減持日期,前置窗口長度,後置窗口長度):
減持時間戳 = datetime.strptime(減持日期,"%Y-%m-%d")
開始日期 = (減持時間戳-timespan*前置窗口長度).strftime("%Y-%m-%d")
print(開始日期)
結束日期 = (減持時間戳+timespan*後置窗口長度).strftime("%Y-%m-%d")
print(結束日期)
clist = data.loc[(data['stkcd'] == 股票代碼) & (data['日期序列'] <= 結束日期) & (data['日期序列'] >= 開始日期), '日超額收益']
區間CAR = sum(clist)
return(區間CAR)

for i in range(111):
with open("15天CAR統計結果.txt",'a') as g:
try:
f = open("事件" + repr(i)+".txt",'r')
data = getlist("CAR" +repr(i)+".txt")
lines = f.readlines()
for line in lines:
stkcd = int(line.split(',')[0].split("\n")[0])
print(stkcd)
eventdate = line.split(',')[1].split("\n")[0]
事件前15天CAR = 區間計數(stkcd, eventdate, 15, 0)
事件後15天CAR = 區間計數(stkcd, eventdate, 0, 15)
print([stkcd, eventdate, 事件前15天CAR, 事件後15天CAR])
g.write(','.join([repr(stkcd), eventdate, repr(事件前15天CAR), repr(事件後15天CAR)])+'\n')
f.close()
except:
print("skip "+repr(i))

七、統計結果樣例股票代碼事件日期事件前15天CAR事件後15天CAR事件前15天公告數事件後15天公告數22014-03-210.1928260.0639818622014-08-29-0.057021-0.03309719622014-09-16-0.031721-0.03163561622015-01-24-0.010155-0.10772231322015-01-28-0.069575-0.04520161022015-07-110.356788-0.126676151622015-07-25-0.1925250.0095171222015-08-040.019329-0.12050872922015-08-270.142061-0.048584221122015-12-070.2429670.221147111622015-12-090.3533910.276527121522015-12-160.2687260.124451172622016-07-07-0.27522-0.133624461822016-08-050.2940570.1905699822016-08-090.2950280.076121715

關於我們歡迎加入Stata連享會(公眾號: StataChina)

相關焦點

  • 教程:Python拆分基因篩選數據
    今天,譚編給大家分享利用Python編程對基因篩選數據文件進行拆分的編程教程。前一段時間,一位本校生科院的同事尋求幫助:怎樣將一個數據量很大的基因篩選數據文件拆分成單個的txt文本文件?為了適應不同的基因篩選實驗數據的處理,python程序運行時,需要一個輸入框,輸入原數據文件名(例如no_ex.cds.align.txt),確定後,python程序就可以執行自動拆分操作了。
  • 入門 | 三行Python代碼,讓數據預處理速度提高2到6倍
    本文可以教你僅使用 3 行代碼,大大加快數據預處理的速度。Python 是機器學習領域內的首選程式語言,它易於使用,也有很多出色的庫來幫助你更快處理數據。但當我們面臨大量數據時,一些問題就會顯現……目前,大數據(Big Data)這個術語通常用於表示包含數十萬數據點的數據集。在這樣的尺度上,工作進程中加入任何額外的計算都需要時刻注意保持效率。
  • 三行Python代碼,讓數據處理速度提高2到6倍
    標準方法讓我們舉一個簡單的例子,在單個文件夾中有一個圖片數據集,其中有數萬張圖片。在這裡,我們決定使用 1000 張。我們希望在所有圖片被傳遞到深度神經網絡之前將其調整為 600×600 像素解析度的形式。
  • 如何用i5實現20倍的Python運行速度?
    這就是我怎麼做的:安裝: % bash Anaconda2-4.3.0-Linux-x86_64.sh安裝英特爾加速器,作為一個單獨的、可開啟關閉的「環境」:% conda config --add channels intel % conda create --name intelpy intelpython2_full python=2運行示例程序
  • 如何在 i5 上實現 20 倍的 Python 運行速度?
    安裝: % bash Anaconda2-4.3.0-Linux-x86_64.sh安裝英特爾加速器,作為一個單獨的、可開啟關閉的「環境」:% conda config --add channels intel % conda create --name intelpy intelpython2_full python=2運行示例程序,看到在我的 openSUSE
  • 一行代碼讓你的Python運行速度提高100倍!Python真強!
    python一直被病垢運行速度太慢,但是實際上python的執行效率並不慢,慢的是python用的解釋器Cpython運行效率太差。「一行代碼讓python的運行速度提高100倍」這絕不是譁眾取寵的論調。我們來看一下這個最簡單的例子,從1一直累加到1億。
  • 如何在Core i5 上實現 20 倍的 Python 運行速度?
    VBox 設置上有 15 到 20 倍的速度提升。我決定對每一個進行十億級測試——運行超過十萬個數字的函數,重複超過一萬次。雖然未必是一個很有意思的程序,但對於加速而言是個不錯的測試。隨時加速 Python我此前寫過一篇文章,討論「Python 加速」( 「accelerated Python」 )使其更適用於大數據和 HPC 應用。
  • 一個簡單的更改讓PyTorch讀取表格數據的速度提高20倍
    我將向您展示我在PyTorch中對表格的數據加載器進行的簡單更改如何將訓練速度提高了20倍以上,而循環沒有任何變化! 這只是PyTorch標準數據加載器的簡單替代品。 對於我正在訓練的模型,可以16分鐘的迭代時間,減少到40秒!所有這些都無需安裝任何新軟體包,不用進行任何底層代碼或任何超參數的更改。
  • Unladen Swallow項目計劃:提高Python速度5倍
    Google的Python工程師發布了一個新項目,目的是讓Python的速度提高至少5倍。新項目名叫Unladen Swallow,意圖尋找新的Python解釋程序虛擬機,新的JIT編譯引擎。第一季度的目標是實現25-35%的性能提升,目前已經完成,代碼發布在Google Code 網站上。
  • 讀取、創建和運行多個文件的3個Python技巧
    動機將代碼投入生產時,你很可能需要處理代碼文件的組織。讀取、創建和運行許多數據文件非常耗時。本文將向你展示如何自動循環訪問目錄中的文件如果不存在嵌套文件,創建它們使用bash for loop運行一個具有不同輸入的文件這些技巧為我在數據科學項目中節省了很多時間。我希望你也會發現它們有用!
  • 如何在Visual Studio創建python文件並運行
    工具Visual Studiopython環境截圖工具技術python在Visual Studio開發工具中,創建python項目,根據項目的需要,新建不同的python文件;然後選擇python文件,進行運行。
  • python實戰演練2:python可執行文件運行不成功怎麼辦
    要談到這個話題,我們首先對如何將python文件製作成exe文件做簡單介紹:眾所周知,python語言作為一種腳本語言,本身是無法自己轉化成可執行文件的,需要藉助第三方工具才能將其轉化為可執行文件(.exe文件)。
  • 數據處理必看:如何讓你的 pandas 循環加快 71803 倍
    python 不能用任何內置函數,而且速度非常慢。在我們的示例中,我們得到了一個具有 65 列和 1140 行的數據幀,它包含 2016-2019 賽季的足球比賽結果。我們要創建一個新的列來指示某個特定的隊是否打過平局。
  • Python數據類型串講(上)
    CDA數據分析師 出品1、什麼是數據學習一門新的程式語言,掌握其語法的底層是我們第一步要做的事。編程的底層也就是我們常說的基礎,下面將從python的基礎中的數據類型開始入門。何為數據?3、數據類型串講python的數據類型根據其結構劃分為兩類:原子類型和結構類型。原子類型是python中最簡單的一種數據類型,或者說是python中最原始的數據類型,僅包含一種值的集合:數字型或字符串型;結構類型則是包含多種值,結構較複雜的集合。
  • Java反射機制,速度提高1000倍
    原文:Java Reflection, 1000x Faster作者:aka Nicolas Laurent譯者:Teixeira10譯者註:在本文中,作者例舉了幾個版本的代碼,利用java發射機制,逐步提高代碼運行速度,同時將Github上的代碼進行展示。
  • 讓 Python 代碼運行更快的最佳方式!
    或者你可以使用Cython,這個項目可以將Python種加上運行時類型信息以便編譯為C,通過這種方式來允許你使用Python代碼。但變通辦法從來都不是理想的。如果我們能夠按原樣使用現有的Python程序並以更快的速度運行它,那不是很好嗎?這正是PyPy允許你做的事情。
  • 想提高計算速度?作為數據科學家你應該知道這些 python 多線程、進程知識
    每個數據科學項目遲早都會面臨一個不可避免的挑戰:速度問題。使用更大的數據集會導致處理速度變慢,因此最終必須想辦法優化算法的運行時間。
  • 用這幾個方法提高pandas運行速度
    因此,如果正確使用pandas的話,它的運行速度應該是非常快的。本篇將要介紹幾種pandas中常用到的方法,對於這些方法使用存在哪些需要注意的問題,以及如何對它們進行速度提升。00         0.5802    2013-01-01 02:00:00         0.5723    2013-01-01 03:00:00         0.5964    2013-01-01 04:00:00         0.592date_time的格式已經自動轉化了,但這還沒完,在這個基礎上,我們還是可以繼續提高運行速度的
  • 搭上python號小火箭,程序運行越來越快!
    但Python運行的慢是歷來被詬病的,一些人黑Python的一點是Python的程序運行速度奇慢。這一方面和語言有關,另一方面可能就是你代碼的問題。其實,無論使用哪種程式語言,特定程序的運行速度很大程度上都取決於該程序的開發人員及其編寫快而優的程序的技巧和能力。語言方面的問題我們解決不了,所以只能在編程技巧上來提高程序的運行效率。
  • 讓Python代碼更快運行的 5 種方法
    Python很簡單易用,但大多數人使用Python都知道在處理密集型cpu工作時,它的數量級依然低於C、Java和JavaScript。但不少第三方不願贅述Python的優點,而是決定自內而外提高其性能。