Большая CSV / обработка текста в Linux - PullRequest
0 голосов
/ 15 марта 2020

У меня есть коллекция довольно больших CSV-файлов (~ 1M записей на 15 МБ +), содержимое которых мне нужно извлечь, переформатировать, а затем добавить в текстовый файл шаблона.

Я написал следующий скрипт python, чтобы сделать это, и он делает то, что я хочу, но работает очень медленно (обработка заняла ~ 15 минут для одного файла), и у меня есть несколько тысяч файлов CSV для обработки ,

Сценарий, который я написал ниже:

import pandas as pd
import shutil as s
from datetime import datetime as dt


dir = '/media/E/data/idb/'
f = '20020401.csv'
outFile = 'importbase.txt'


df = pd.read_csv(dir + f)
df["DataDate"] = pd.to_datetime(df["DataDate"]).view('int64') 
df["Expiration"] = pd.to_datetime(df["Expiration"], format='%m/%d/%Y')

df["measurement"] = ['options' for t in range(len(df))]
lines = [str(df["measurement"][d])
        + ",type=options"
        + " " 
        + "ticker=" + str(df["UnderlyingSymbol"][d])
        + ",symbol=" + str(df["OptionSymbol"][d])
        + ",expDate=" + str(df["Expiration"][d])
        + ",cont=" + str(df["Type"][d])
        + ",price=" + str(df["UnderlyingPrice"][d])
        + ",strike=" + str(df["Strike"][d])
        + ",last=" + str(df["Last"][d])
        + ",bid=" + str(df["Bid"][d])
        + ",ask=" + str(df["Ask"][d])
        + ",volume=" + str(df["Volume"][d])
        + ",OI=" + str(df["OpenInterest"][d])
        + ",IV=" + str(df["IV"][d])
        + ",delta=" + str(df["Delta"][d])
        + ",gamma=" + str(df["Gamma"][d])
        + ",theta=" + str(df["Theta"][d])
        + ",vega=" + str(df["Vega"][d])
        + ",aka=" + str(df["AKA"][d])
        + " " + str(df["DataDate"][d]) for d in range(len(df))]


a = s.copyfile(dir + outFile, dir + 'import.txt')               
file = open(a, 'a+')
for item in lines:
        file.write("%s\n" % item)
file.close()

Файл importbase.txt является файлом шаблона. Мне нужно добавить свои данные к их содержимому, а затем сохранить их как import.txt для обработки. Примеры importbase, import и my CSV ниже:

importbase.txt

# DDL
CREATE DATABASE import

# DML
# CONTEXT-DATABASE: import

import.txt

# DDL
CREATE DATABASE import

# DML
# CONTEXT-DATABASE: import
options,type=options ticker=A,symbol=A020420C00015000,expDate=2002-04-20 00:00:00,cont=call,price=36.53,strike=15.0,last=0.0,bid=21.0,ask=22.3,volume=0,OI=0,IV=0.6145,delta=0.9987,gamma=0.0,theta=0.6848,vega=0.0aka=ADC 1017619200000000000
options,type=options ticker=A,symbol=A020420P00015000,expDate=2002-04-20 00:00:00,cont=put,price=36.53,strike=15.0,last=0.0,bid=0.0,ask=0.1,volume=0,OI=0,IV=0.5964,delta=0.0,gamma=0.0,theta=0.0,vega=0.0aka=APC 1017619200000000000
options,type=options ticker=A,symbol=A020420C00017500,expDate=2002-04-20 00:00:00,cont=call,price=36.53,strike=17.5,last=0.0,bid=18.7,ask=19.5,volume=0,OI=0,IV=0.6145,delta=0.9987,gamma=0.0,theta=0.6371,vega=0.0aka=ADW 1017619200000000000
options,type=options ticker=A,symbol=A020420P00017500,expDate=2002-04-20 00:00:00,cont=put,price=36.53,strike=17.5,last=0.0,bid=0.0,ask=0.1,volume=0,OI=0,IV=0.5964,delta=0.0,gamma=0.0,theta=0.0,vega=0.0aka=APW 1017619200000000000

20020401.csv

UnderlyingSymbol,UnderlyingPrice,Exchange,OptionSymbol,OptionExt,Type,Expiration,DataDate,Strike,Last,Bid,Ask,Volume,OpenInterest,IV,Delta,Gamma,Theta,Vega,AKA
A,36.53,*,A020420C00015000,,call,04/20/2002,04/01/2002,15,0,21,22.3,0,0,0.6145,0.9987,0,0.6848,0,ADC
A,36.53,*,A020420P00015000,,put,04/20/2002,04/01/2002,15,0,0,0.1,0,0,0.5964,0,0,0,0,APC
A,36.53,*,A020420C00017500,,call,04/20/2002,04/01/2002,17.5,0,18.7,19.5,0,0,0.6145,0.9987,0,0.6371,0,ADW
A,36.53,*,A020420P00017500,,put,04/20/2002,04/01/2002,17.5,0,0,0.1,0,0,0.5964,0,0,0,0,APW
A,36.53,*,A020420C00020000,,call,04/20/2002,04/01/2002,20,0,16.2,17,0,0,0.6145,0.9987,0,0.5882,0.0002,ADD
A,36.53,*,A020420P00020000,,put,04/20/2002,04/01/2002,20,0,0,0.1,0,0,0.5964,0,0,-0.0006,0.0001,APD
A,36.53,*,A020420C00022500,,call,04/20/2002,04/01/2002,22.5,5.7,13.7,14.5,0,5,0.6145,0.9985,0.0001,0.5092,0.0053,ADX
A,36.53,*,A020420P00022500,,put,04/20/2002,04/01/2002,22.5,0,0,0.1,0,1545,0.5964,-0.0001,0.0001,-0.0214,0.0036,APX
A,36.53,*,A020420C00025000,,call,04/20/2002,04/01/2002,25,11.6,11.2,12,0,545,0.6145,0.9963,0.0015,0.1189,0.0612,ADE
A,36.53,*,A020420P00025000,,put,04/20/2002,04/01/2002,25,0,0,0.1,0,882,0.5964,-0.0019,0.0012,-0.2882,0.0485,APE
A,36.53,*,A020420C00030000,,call,04/20/2002,04/01/2002,30,6.5,6.4,6.9,80,2357,0.6145,0.9314,0.0259,-6.1328,1.0651,ADF

Я использую bash изрядное количество, но задаюсь вопросом, может ли что-то вроде sed или awk лучше подойти для задачи более низкого уровня, такой как эта, где время обработки скорее всего, будет проблемой. Любое руководство по подходу приветствуется.

Ответы [ 3 ]

3 голосов
/ 16 марта 2020

Я не решаюсь опубликовать это как ответ, потому что это просто предположение. Но вы, скорее всего, сэкономите время, перебирая строки данных и форматируя одну строку вместо объединения нескольких строк.

import pandas as pd
import shutil as s
from datetime import datetime as dt

dir = '/media/E/data/idb/'
f = '20020401.csv'
outFile = 'importbase.txt'


df = pd.read_csv(dir + f)
df["DataDate"] = pd.to_datetime(df["DataDate"]).view('int64') 
df["Expiration"] = pd.to_datetime(df["Expiration"], format='%m/%d/%Y')

df["measurement"] = ['options' for t in range(len(df))]

a = s.copyfile(dir + outFile, dir + 'import.txt')               
with open(a, 'a+') as file:
    for index, row in df.iterrows():
        file.write(
            "{measurement},type=options "
            "ticker={UnderlyingSymbol}"
            ",symbol={OptionSymbol}"
            ",expDate={Expiration}"
            ",cont={Type}"
            ",price={UnderlyingPrice}"
            ",strike={Strike}"
            ",last={Last}"
            ",bid={Bid}"
            ",ask={Ask}"
            ",volume={Volume}"
            ",OI={OpenInterest}"
            ",IV={IV}"
            ",delta={Delta}"
            ",gamma={Gamma}"
            ",theta={Theta}"
            ",vega={Vega}"
            ",aka={AKA}"
            " {DataDate}".format_map(row))

На самом деле, здесь pandas нет реального преимущества. Вы занимаете много места при построении фрейма данных, но все равно нужно пройти через переменную python для форматирования, так что просто используйте обычный CSV-модуль

import csv
import shutil as s
from datetime import datetime as dt

dir = '/media/E/data/idb/'
f = '20020401.csv'
outFile = 'importbase.txt'

a = s.copyfile(dir + outFile, dir + 'import.txt')               

with open(dir + f) as in_fp, open(a, "a") as out_fp:
    reader = csv.DictReader(in_fp)
    for row in reader:
        # todo: figure out conversions outside pandas
        #row["DataDate"] = ?
        #row["Expiration"] = ? 
        row["measurement"] = "options"
        file.write(
            "{measurement},type=options "
            "ticker={UnderlyingSymbol}"
            ",symbol={OptionSymbol}"
            ",expDate={Expiration}"
            ",cont={Type}"
            ",price={UnderlyingPrice}"
            ",strike={Strike}"
            ",last={Last}"
            ",bid={Bid}"
            ",ask={Ask}"
            ",volume={Volume}"
            ",OI={OpenInterest}"
            ",IV={IV}"
            ",delta={Delta}"
            ",gamma={Gamma}"
            ",theta={Theta}"
            ",vega={Vega}"
            ",aka={AKA}"
            " {DataDate}".format_map(row))
2 голосов
/ 16 марта 2020

Вот как выполнить преобразование в awk (используя GNU awk для mktime ()):

$ cat tst.awk
BEGIN {
    n = split("                                         \
                ticker          UnderlyingSymbol        \
                symbol          OptionSymbol            \
                expDate         Expiration              \
                cont            Type                    \
                price           UnderlyingPrice         \
                strike          Strike                  \
                last            Last                    \
                bid             Bid                     \
                ask             Ask                     \
                volume          Volume                  \
                OI              OpenInterest            \
                IV              IV                      \
                delta           Delta                   \
                gamma           Gamma                   \
                theta           Theta                   \
                vega            Vega                    \
                aka             AKA                     \
                DataDate        DataDate                \
        ", outInNameMap)

    for (i=1; i<n; i+=2) {
        outFldName = outInNameMap[i]
        inFldName  = outInNameMap[i+1]
        inNames2outNrs[inFldName]   = ++numOutFlds
        outNrs2outNames[numOutFlds] = outFldName
    }

    dateFmt["expDate"]  = "iso8601"
    dateFmt["DataDate"] = "epoch"

    FS=OFS=","
}

FNR == 1 {
    for (inFldNr=1; inFldNr<=NF; inFldNr++) {
        inFldName = $inFldNr
        outFldNr  = inNames2outNrs[inFldName]
        outNrs2inNrs[outFldNr] = inFldNr
    }
    next
}

{
    printf "options,type=options"
    for (outFldNr=1; outFldNr<=numOutFlds; outFldNr++) {
        outFldName = outNrs2outNames[outFldNr]
        inFldNr = outNrs2inNrs[outFldNr]
        fldVal  = $inFldNr
        if ( outFldName in dateFmt) {
            split(fldVal,d,"/")
            if ( dateFmt[outFldName] == "iso8601" ) {
                fldVal = sprintf("%s-%s-%s 00:00:00", d[3], d[1], d[2])
            }
            else if ( dateFmt[outFldName] == "epoch" ) {
                fldVal = mktime(sprintf("%s %s %s 00 00 00", d[3], d[1], d[2]))
            }
        }
        pfx = (outFldNr==numOutFlds ? " " : (outFldNr>1 ? OFS : " ") outFldName "=")
        printf "%s%s", pfx, fldVal
    }
    print ""
}

.

$ awk -f tst.awk file.csv
options,type=options ticker=A,symbol=A020420C00015000,expDate=2002-04-20 00:00:00,cont=call,price=36.53,strike=15,last=0,bid=21,ask=22.3,volume=0,OI=0,IV=0.6145,delta=0.9987,gamma=0,theta=0.6848,vega=0,aka=ADC 1017640800
options,type=options ticker=A,symbol=A020420P00015000,expDate=2002-04-20 00:00:00,cont=put,price=36.53,strike=15,last=0,bid=0,ask=0.1,volume=0,OI=0,IV=0.5964,delta=0,gamma=0,theta=0,vega=0,aka=APC 1017640800
options,type=options ticker=A,symbol=A020420C00017500,expDate=2002-04-20 00:00:00,cont=call,price=36.53,strike=17.5,last=0,bid=18.7,ask=19.5,volume=0,OI=0,IV=0.6145,delta=0.9987,gamma=0,theta=0.6371,vega=0,aka=ADW 1017640800
options,type=options ticker=A,symbol=A020420P00017500,expDate=2002-04-20 00:00:00,cont=put,price=36.53,strike=17.5,last=0,bid=0,ask=0.1,volume=0,OI=0,IV=0.5964,delta=0,gamma=0,theta=0,vega=0,aka=APW 1017640800
options,type=options ticker=A,symbol=A020420C00020000,expDate=2002-04-20 00:00:00,cont=call,price=36.53,strike=20,last=0,bid=16.2,ask=17,volume=0,OI=0,IV=0.6145,delta=0.9987,gamma=0,theta=0.5882,vega=0.0002,aka=ADD 1017640800
options,type=options ticker=A,symbol=A020420P00020000,expDate=2002-04-20 00:00:00,cont=put,price=36.53,strike=20,last=0,bid=0,ask=0.1,volume=0,OI=0,IV=0.5964,delta=0,gamma=0,theta=-0.0006,vega=0.0001,aka=APD 1017640800
options,type=options ticker=A,symbol=A020420C00022500,expDate=2002-04-20 00:00:00,cont=call,price=36.53,strike=22.5,last=5.7,bid=13.7,ask=14.5,volume=0,OI=5,IV=0.6145,delta=0.9985,gamma=0.0001,theta=0.5092,vega=0.0053,aka=ADX 1017640800
options,type=options ticker=A,symbol=A020420P00022500,expDate=2002-04-20 00:00:00,cont=put,price=36.53,strike=22.5,last=0,bid=0,ask=0.1,volume=0,OI=1545,IV=0.5964,delta=-0.0001,gamma=0.0001,theta=-0.0214,vega=0.0036,aka=APX 1017640800
options,type=options ticker=A,symbol=A020420C00025000,expDate=2002-04-20 00:00:00,cont=call,price=36.53,strike=25,last=11.6,bid=11.2,ask=12,volume=0,OI=545,IV=0.6145,delta=0.9963,gamma=0.0015,theta=0.1189,vega=0.0612,aka=ADE 1017640800
options,type=options ticker=A,symbol=A020420P00025000,expDate=2002-04-20 00:00:00,cont=put,price=36.53,strike=25,last=0,bid=0,ask=0.1,volume=0,OI=882,IV=0.5964,delta=-0.0019,gamma=0.0012,theta=-0.2882,vega=0.0485,aka=APE 1017640800
options,type=options ticker=A,symbol=A020420C00030000,expDate=2002-04-20 00:00:00,cont=call,price=36.53,strike=30,last=6.5,bid=6.4,ask=6.9,volume=80,OI=2357,IV=0.6145,delta=0.9314,gamma=0.0259,theta=-6.1328,vega=1.0651,aka=ADF 1017640800

Я не совсем уверен, какое это окончательное значение на ваших выходных строках, кажется, есть некоторая вариация секунд с начала эпохи, но я оставлю это в качестве упражнения для вас, чтобы исправить это при необходимости. Я использовал больше временных переменных, чем необходимо, и использовал четкие имена для всех из них, чтобы было очевидно, что происходит, и поэтому не нужно комментировать, чтобы объяснить это, и вы сможете легко их использовать.

2 голосов
/ 16 марта 2020

Вы можете сделать это с помощью awk, но вам лучше использовать анализатор CSV, и, поскольку вы уже используете Python, лучше использовать его, вероятно, ответ.

Суть вашей проблемы - воспроизвести CSV в виде списка пар имя-значение, разделенных запятыми. Для этого это сделает работу, и я ожидаю, что она будет работать довольно хорошо.

#! /usr/bin/env python3
import csv

fieldnames = ('type', 'ticker', 'symbol', 'expDate', 'cont',
                  'price', 'strike', 'last', 'bid', 'ask', 'volume',
                  'OI', 'IV', 'delta', 'gamma',
                  'UnderlyingSymbol', 'UnderlyingPrice', 'Exchange',
                  'OptionSymbol', 'OptionExt', 'Type', 'Expiration', 'DataDate',
                  'Strike', 'Last', 'Bid', 'Ask', 'Volume',
                  'OpenInterest', 'IV', 'Delta', 'Gamma', 'Theta', 'Vega', 'AKA')

with open('input.csv', newline='') as csvfile:
    rows = csv.DictReader(csvfile, fieldnames)
    for i, row in enumerate(rows):
        if i == 0:
            continue
        line = ','.join( [ '%s=%s' % (k,v) for k,v in row.items() ] )
        print( 'options,%s' % line )

производство продукции:

$ ./convert.py | nl
     1  options,type=    A,ticker=36.53,symbol=*,expDate=A020420P00015000,cont=,price=put,strike=04/20/2002,last=04/01/2002,bid=15,ask=0,volume=0,OI=0.1,IV=None,delta=0,gamma=0.5964,UnderlyingSymbol=0,UnderlyingPrice=0,Exchange=0,OptionSymbol=0,OptionExt=APC,Type=None,Expiration=None,DataDate=None,Strike=None,Last=None,Bid=None,Ask=None,Volume=None,OpenInterest=None,Delta=None,Gamma=None,Theta=None,Vega=None,AKA=None
     2  options,type=    A,ticker=36.53,symbol=*,expDate=A020420C00017500,cont=,price=call,strike=04/20/2002,last=04/01/2002,bid=17.5,ask=0,volume=18.7,OI=19.5,IV=None,delta=0,gamma=0.6145,UnderlyingSymbol=0.9987,UnderlyingPrice=0,Exchange=0.6371,OptionSymbol=0,OptionExt=ADW,Type=None,Expiration=None,DataDate=None,Strike=None,Last=None,Bid=None,Ask=None,Volume=None,OpenInterest=None,Delta=None,Gamma=None,Theta=None,Vega=None,AKA=None
     3  options,type=    A,ticker=36.53,symbol=*,expDate=A020420P00017500,cont=,price=put,strike=04/20/2002,last=04/01/2002,bid=17.5,ask=0,volume=0,OI=0.1,IV=None,delta=0,gamma=0.5964,UnderlyingSymbol=0,UnderlyingPrice=0,Exchange=0,OptionSymbol=0,OptionExt=APW,Type=None,Expiration=None,DataDate=None,Strike=None,Last=None,Bid=None,Ask=None,Volume=None,OpenInterest=None,Delta=None,Gamma=None,Theta=None,Vega=None,AKA=None
     4  options,type=    A,ticker=36.53,symbol=*,expDate=A020420C00020000,cont=,price=call,strike=04/20/2002,last=04/01/2002,bid=20,ask=0,volume=16.2,OI=17,IV=None,delta=0,gamma=0.6145,UnderlyingSymbol=0.9987,UnderlyingPrice=0,Exchange=0.5882,OptionSymbol=0.0002,OptionExt=ADD,Type=None,Expiration=None,DataDate=None,Strike=None,Last=None,Bid=None,Ask=None,Volume=None,OpenInterest=None,Delta=None,Gamma=None,Theta=None,Vega=None,AKA=None
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...