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

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

新規登録して質問してみよう
ただいま回答率
85.37%
CSV

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

Blockchain

Blockchain(ブロックチェーン)とは、分散型台帳技術もしくは分散型ネットワークのことを指します。クラウド上のデータを分散し、ノード間でデータの相違があった際には他ノードの合意によって信頼性が高いデータを判断。データの確保および信憑性を保持する技術です。

SQL Server

SQL Serverはマイクロソフトのリレーショナルデータベース管理システムです。データマイニングや多次元解析など、ビジネスインテリジェンスのための機能が備わっています。

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

Python 3.x

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

Q&A

解決済

2回答

1876閲覧

csvファイルを前から3列、後ろから2列といった形で取得したい

yostito

総合スコア7

CSV

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

Blockchain

Blockchain(ブロックチェーン)とは、分散型台帳技術もしくは分散型ネットワークのことを指します。クラウド上のデータを分散し、ノード間でデータの相違があった際には他ノードの合意によって信頼性が高いデータを判断。データの確保および信憑性を保持する技術です。

SQL Server

SQL Serverはマイクロソフトのリレーショナルデータベース管理システムです。データマイニングや多次元解析など、ビジネスインテリジェンスのための機能が備わっています。

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

Python 3.x

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

0グッド

0クリップ

投稿2019/02/09 06:45

前提・実現したいこと

列数が一定出ないcsvファイルがあり、前から1,2,3列と後ろから1,2列だけを取得してデータベース入れたいです。
また、前から3列目には不要な文字が含まれており(”と[]),それを取り除きたいです。
対象のcsvファイルが1ファイル100万行で1000ファイル程度ある為、パフォーマンスが良い方法で行いたいです。

発生している問題

下記コードの方法で、1行ずつ列数を取得して列数別に処理しているのですが、20万行処理するのに1時間程度かかっています。単純にcsvファイルを読み込んでSQL Serverに格納するだけならば100万行で2分-3分で終わるので、そのくらいのパフォーマンスを出したいです。
###csvファイルサンプル

aaa,1445965775,["a"],1,0.0027 bbb,1445965775,["b","bb","bbb"],1,0.05075575 ccc,1445965775,["c","cc"],0,2.86008262

該当のソースコード

python

1ソースコード 2file_list = sorted(glob.glob(r'/ファイルパス/*.csv')) 3##カラム定義 4cols = ['txid', 'blocktime','addresses','n','value'] 5##SQL Serverに入れる用データフレーム 6df_vout = pd.DataFrame(index=[], columns=cols) 7##tmp用データフレーム 8record = pd.DataFrame(index=[], columns=cols) 9 10for filename in file_list: 11 ##SQL Serverに入れる用データフレーム 12 df_vout = pd.DataFrame(index=[], columns=cols) 13 ##tmp用データフレーム 14 record = pd.DataFrame(index=[], columns=cols) 15 with open(filename) as f: 16 reader = csv.reader(f) 17 #下記rowにはリストが入る 18 #1行ずつ取り出し 19 for row in reader: 20 print(row_count) 21 #原則として要素数は5個。5個の場合はvalueだけfloatで変換して素直に入れる。 22 if len(row)==5: 23 #アドレス列は"[アドレス]”という形式で入るので、不要な[]"を空白に置換 24 row[2] = row[2].replace('[','') 25 row[2] = row[2].replace(']','') 26 row[2] = row[2].replace('"','') 27 #valueは指数表記で入ってくることがあるので、floatで数値に変換してあげる 28 record =pd.Series([row[0],row[1],row[2],row[3],float(row[4])],index=df_vout.columns) 29 df_vout =df_vout.append(record,ignore_index=True) 30 #6以上の場合はアドレスに2つ以上あるので、結合する必要があり。最悪結合しないで、最初のアドレスでOK 31 elif len(row)==6: 32 concati_address_6 = row[2]+row[3] 33 concati_address_6 = concati_address_6.replace('[','') 34 concati_address_6 = concati_address_6.replace(']','') 35 concati_address_6 = concati_address_6.replace('"','') 36 record = pd.Series([row[0],row[1],concati_address_6,row[4],float(row[5])], index=df_vout.columns) 37 df_vout = df_vout.append(record,ignore_index=True) 38 39 #ファイル単位でSQL Serverに書き込み 40 df_vout.columns = ['txid', 'blocktime','addresses','n','value'] 41 df_vout.to_sql("テーブル名", engine, if_exists='append', index=False, chunksize=8)

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hayataka2049

2019/02/09 06:51

前から3行、後ろから2行では?
yostito

2019/02/09 07:00

コメントありがとうございます。 サンプルの例ですと、下記のような形に整形したいので、前から3列、後ろから2列取り込みたいのです。 aaa,1445965775,a,1,0.0027 bbb,1445965775,b,1,0.05075575 ccc,1445965775,c,0,2.86008262
hayataka2049

2019/02/09 07:01

もしかして、a,b,c,d,e,fからa,b,c,e,fを取るということでしょうか。 bbb,1445965775,["b","bb","bbb"],1,0.05075575 みたいな例は何列になるとお考えですか?(途中の[]間のカンマの扱い)
yostito

2019/02/09 07:02

はい、そのように取りたいと思っています。上記例でカンマ区切りのファイルですと、7列になると考えています
guest

回答2

0

以下のように中間ファイルを介してデータを整形するのが遠回りのようで近道かと思います。

Python

1import os 2 3def conv_csv(inp_path): 4 5 tmp_path = inp_path + '.tmp' 6 with open(inp_path) as fin: 7 with open(tmp_path,'w') as fout: 8 for line in fin: 9 # ~,["a","aa"],~ -> ~,|"a","aa"|,~ 10 line = line.replace('[','|').replace(']','|') 11 fout.write(line) 12 13 import csv 14 ret_path = inp_path + '.ret' 15 with open(tmp_path, newline='') as fin: 16 reader = csv.reader(fin, delimiter=',', quotechar='|') 17 with open(ret_path,'w', newline='') as fout: 18 writer = csv.writer(fout) 19 for row in reader: 20 # 3列目「"a","aa"」から「a」のみ抽出して連結しなおす 21 r2 = row[2].split(',')[0].strip('"') 22 writer.writerow([row[0],row[1],r2,row[3],row[4]]) 23 24 os.remove(tmp_path) 25 return ret_path 26 27 28ret_path = conv_csv('inp.csv') # csvファイルサンプル 29 30import pandas as pd 31df = pd.read_csv(ret_path,header=None) 32os.remove(ret_path) 33print(df) 34""" 35 0 1 2 3 4 360 aaa 1445965775 a 1 0.002700 371 bbb 1445965775 b 1 0.050756 382 ccc 1445965775 c 0 2.860083 39"""

投稿2019/02/09 07:56

can110

総合スコア38339

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yostito

2019/02/09 10:11

コード含めて回答頂きありがとうございます!ご教授頂いた方法でも試してみようと思います!
guest

0

ベストアンサー

とりあえず、DataFrame.appendは確実に遅いので、リストに格納していって最後にDataFrameにした方が速いと思います。

https://qiita.com/studio_haneya/items/35951c56decd212ba41e

投稿2019/02/09 07:01

hayataka2049

総合スコア30935

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yostito

2019/02/09 10:10

ありがとうございます!ご教授頂いた方法でやってみたら、とても速くなりました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問