質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

91.01%

  • Python 3.x

    4084questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

  • CSV

    509questions

    CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

300kb程度の大量のcsvを高速に読み込みたい。

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 567

sasaya

score 2

前提・実現したいこと

大量(3,574個程度)のcsvファイルを高速に読み込みたいです。
Pythonの勉強も兼ねて,現在過去10年程度の期間において、自分の作った株取引ルールが機能するかを検証するためのプログラムを作成中です。そのためにcsvで保存されたデータをなるべく早く読み込みたいです。

現在は xarrayを用いて3次元データとして扱おうとしておりますがより高速な方法がありましたら教えていただけたら幸いです。

使用しているデータは株価データ集 for 日本株時系列データ 2000年-2017年6月30日です。

発生している問題・エラーメッセージ

Ipythonで%time , %run -p で動作時間を計測した結果 
570秒~1500秒もの時間がかかっており,xarray.concat()だけで40秒程度かかっております。

一例

8383269 function calls (8141048 primitive calls) in 905.298 seconds
   Ordered by: internal time
   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
       25  384.667   15.387  384.667   15.387 {built-in method numpy.core.multiarray.concatenate}
        1  244.721  244.721  711.806  711.806 combine.py:286(_dataarray_concat)
       24  130.215    5.426  130.215    5.426 {method 'acquire' of '_thread.lock' objects}
        1   55.747   55.747  904.727  904.727 read_data.py:3(<module>)
        1   13.966   13.966   13.966   13.966 {built-in method pandas._libs.lib.infer_datetimelike_array}
     3960    7.479    0.002    8.485    0.002 indexing.py:480(__setitem__)
    11878    6.137    0.001    6.137    0.001 {built-in method pandas._libs.lib.array_equivalent_object}

    

該当のソースコード

import os
import numpy as np
import xarray as xr
import pandas as pd
from multiprocessing import Pool
import numba

_path = os.path.abspath(os.path.dirname(__file__)) + '/st-jp-2000-2017.6/dd_full'
_ref = pd.read_csv(os.path.abspath(os.path.dirname(__file__)) + '/st-jp-2000-2017.6/dd/1301.CSV',
                   index_col=0, parse_dates=True,
                   names=["Open", "High", "Low", "Close", "Volume", "margin selling", "margin debt"])


@numba.jit
def in_parallel():
    global _path
    files = os.listdir(_path)
    p = Pool()
    stock_db = (p.map(csv_to_xarray, files))
    p.close()
    p.join()
    print("loading complete")
    return stock_db


def in_serial():
    global _path
    files = os.listdir(_path)
    stock_db = [csv_to_xarray(file) for file in files]
    print("loading complete")
    return stock_db


@numba.jit
def csv_to_xarray(file):
    """
    :type file: str
    :rtype: DataArray
    """
    global _ref
    global _path
    data = pd.read_csv(_path + '/' + file, index_col=0, parse_dates=True,
                       names=["Open", "High", "Low", "Close", "Volume", "margin selling", "margin debt"])

    data = adjust_index_length(data, _ref)

    da = xr.DataArray(data.values.reshape(len(data.index), 1, len(data.columns)),
                      coords=[data.index, [file[0:4]],
                              ["Open", "High", "Low", "Close", "Volume", "margin selling", "margin debt"]],
                      dims=["date", "code", "values"])
    return da


@numba.jit
def adjust_index_length(data, ref):
    """
    :type ref: DataFrame
    :type data: DataFrame
    :rtype: DataFrame
    """
    time_diff = set(ref.index) - set(data.index)
    if len(time_diff) == 0:
        data.drop(set(data.index) - set(ref.index), inplace=True)
        return data.sort_index()

    else:
        df = pd.DataFrame(index=time_diff, columns=["Open", "High", "Low", "Close", "Volume",
                                                                       "margin selling", "margin debt"])
        df = df.append(data)
        return df.sort_index()


if __name__ == '__main__':  # ここで この処理を行わないとサブプロセスが再帰的に生成される?(Winだけ?)
    __spec__ = "ModuleSpec(name='builtins', loader=<class '_frozen_importlib.BuiltinImporter'>)"

    print(xr.concat(in_parallel(), dim='code'))
    #print(xr.concat(in_serial(), dim='code'))

    

試したこと

multiprocessingを用いて並列に走らせてみて,ディスク使用率は常時100%になっていることを確認しました。また,numbaの使用を検討中であります。
そもそもpythonだけですべて行わず,元データの選別等をC等で行うことも検討しております。

補足情報(言語/FW/ツール等のバージョンなど)

現在の動作環境は以下の通りです。
core i3-6100T 3.2GHz
Ram ddr3 8GB

Windows 10
Anaconda
Python 3.6

今後 core i7 ないし Ryzen 7を積んだpcに乗り換える予定があります。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+6

自分の作った株取引ルールが機能するかを検証するためのプログラムを作成中です。
使用しているデータは株価データ集 for 日本株時系列データ 2000年-2017年6月30日です。

わざわざ低速なフォーマットを採用するメリットは一つもありません。
CSVを採用するケースなんて、非エンジニアの上司や顧客がExcelで見ないとやだやだって駄々こねたときだけです。

この馬鹿げた処理速度の原因の殆どは読み込みとソートに終始しているので、SQLiteに任せたほうが間違いなく速いです。
ローカルでソート処理等を書いてはいけません。
CSVファイル -> SQLite等の高速なフォーマットに一度移しておき、SQL文をつかって絞込やソートを行いましょう。

検証フェイズが終わった後本番で使う時の事を考えた場合、
株価は毎日のように更新されますが、SQLiteに変換するプログラムを用意してまわしておけば良いでしょう。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/10/30 15:24 編集

    やはり、横着せずにsqlにした方がいいんですね。ありがとうございます

    別件ですが
    元々ソートされているものに対して set()で集合にして取った差をインデックスにDataFrameを作ると何故ソートされてない状態になってしまうのかというのが現在ちょっと引っかかっています。

    キャンセル

  • 2017/10/30 11:45

    http://uxmilk.jp/14834
    Pythonに関しては詳しくないのでブログ記事の引用で失礼します。

    setは順番の概念を持たないので、おもちゃ箱のような空間に無造作に放り込まれるのでしょうね。
    その後重複チェック処理にかけられますので、メモリ空間上に設置されたアイテムはこねくり回されてぐちゃぐちゃになるのだろうと「完全に憶測」ですが想像してます。

    ソート済みの要素を重複排除の為だけにsetを使うのはやめたほうが良さそうですね。

    キャンセル

  • 2017/10/30 22:00

    大変丁寧でかつ迅速な回答をいただき、ありがとうございます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 91.01%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Python 3.x

    4084questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

  • CSV

    509questions

    CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。