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

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

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

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

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

pandas

Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

Q&A

解決済

1回答

1378閲覧

pythonプログラムの高速化

kak

総合スコア27

CSV

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

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

pandas

Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

0グッド

0クリップ

投稿2019/04/17 11:30

編集2019/04/23 12:28

いつも勉強させていただいてます。
AnacondaのPython3の環境下で以下のプログラムを実行しています。

カレントディレクトリに以下のようなカラムが2列あるtest.csvがあります。
各columnのindex0に'sample1','sample2'、index1以降にデータが247個入っています。
まず、test.csvのcolumn0,1をそれぞれの数値がそれぞれのカラムに入るように11列に分け、index1-247をそれぞれsample1.csv,sample2.csv...sample247.csvとして保存します。

0

0 sample1
1 VAL H 1 103.30 68.2 76.95 67.3 26.35 70.9 76.95 66.6 26.35 73.3
2 VAL H 2 103.30 68.2 76.95 67.3 26.35 70.9 76.95 66.6 26.35 73.3
3 VAL H 3 103.30 68.2 76.95 67.3 26.35 70.9 76.95 66.6 26.35 73.3
4 VAL H 4 103.30 68.2 76.95 67.3 26.35 70.9 76.95 66.6 26.35 73.3

... ... .. .. ... ... ... ... ... ... ... ... ... ...
3 VAL H 246 103.30 68.2 76.95 67.3 26.35 70.9 76.95 66.6 26.35 73.3
4 VAL H 247 103.30 68.2 76.95 67.3 26.35 70.9 76.95 66.6 26.35 73.3

sample*.csvの左端に以下のtest.csvのindex0の2列を縦に挿入。

0 1

0
NaN sample1 sample2

以下のような形になります。

0     1   2 3 4 5 6      9  10 11 12  13
1 sample1 ASP H 112 -20.93 -14.9 ... -18.97 -50.3 -1.96 -3.9 -18.98
2 sample2 ASP H 112 -20.93 -14.9 ... -18.97 -50.3 -1.96 -3.9 -18.98

この一つのCSVファイル中でindex2のカラム4~13の値がindex1にあるsample1のそれぞれの数値と異なる数値を含む行のみ取り出し、この処理をカレントディレクトリにあるsample.csvファイルすべてで行い、一つのファイルで出力したいと思っています。
以下のようなプログラムを作成し、目的の値は得られましたが、時間がかかりました。

import pandas as pd df_test=pd.read_csv("../test.csv",sep=",",header=None,index_col=0) for t in range(1,3): sample_files=pd.read_csv("sample%s.csv" % (t),sep=",",index_col=0) test_id=pd.concat([df_test.iloc[0,:],sample_files],axis=1) df_frame=pd.DataFrame(test_id.iloc[0,:]).T for i in range(1,247): df_diff=test_id.iloc[i,4:]-test_id.iloc[0,4:] df_diff_id=pd.concat([test_id.iloc[i,:4],df_diff]) for k in range(10): if df_diff[k] !=0.0: df_frame=df_frame.append(df_diff,ignore_index=True) df_frame_unique=df_frame.drop_duplicates() df_frame_unique.to_csv("result.csv",sep=",") print(df_frame_unique)

そこで以下の様にプログラムを修正し、目的のものが得られました。

df_result=pd.DataFrame() import pandas as pd df_test=pd.read_csv("../test.csv",sep=",",header=None,index_col=0) for t in range(1,3): sample_files=pd.read_csv("sample%s.csv" % (t),sep=",",index_col=0) test_id=pd.concat([df_test.iloc[0,:],test_files],axis=1) df_frame=pd.DataFrame(test_id.iloc[0,:]).T for i in range(1,247): df_diff=test_id.iloc[i,4:]-test_id.iloc[0,4:] df_diff_id=pd.concat([df_test.iloc[i,:4],df_diff]) if df_diff.sum() ! = 0: df_frame=df_frame.append(df_diff,ignore_index=True) df_result=pd.concat([df_result,df_frame]) print(df_result) df_result.to_csv("result.csv",sep=",")

最初のプログラムで時間がかかり過ぎたのと一つのファイルで出力できていなかったので質問させて頂きましたが、質問を修正しているうちに2つ目のプログラムでよいことに気付きました。
ですが、折角ですので勉強のため、修正点やほかにもっといい方法があれば教えてください

ご指摘いただいたようにファイル出力をループの外にだして以下になりました。

df_result=pd.DataFrame() import pandas as pd df_test=pd.read_csv("../test.csv",sep=",",header=None,index_col=0) for t in range(1,3): sample_files=pd.read_csv("sample%s.csv" % (t),sep=",",index_col=0) test_id=pd.concat([df_test.iloc[0,:],test_files],axis=1) df_frame=pd.DataFrame(test_id.iloc[0,:]).T for i in range(1,247): df_diff=test_id.iloc[i,4:]-test_id.iloc[0,4:] df_diff_id=pd.concat([df_test.iloc[i,:4],df_diff]) if df_diff.sum() != 0: df_frame=df_frame.append(df_diff,ignore_index=True).drop_duplicates() df_result=pd.concat([df_result,df_frame]) print(df_result) df_result.to_csv("result.csv",sep=",")

ちなみに処理時間は以下の様でした。
第一ループ内で出力(for i in range(1,247)と同じインデント)
elapsed time:19.02880597114563
第2ループ内で出力(df_result=pd.concat...と同じインデント)
elapsed time:4.529508113861084
ループ外で出力
elapsed time:2.024280071258545

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

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

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

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

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

hayataka2049

2019/04/17 12:57

>df_testのリストを元に次々に取り込み や >test_idによりサンプル名をtest_filesに追加 など、それまでに説明されていない言葉が次々に出てきても理解できないです。率直に言って、読んでも何がしたいのかよくわからなかったです。説明を改善したほうが回答が得られやすいと思います。 途中の過程はともかく、最終的にやりたいことはそれほど難しくないような気もするので、「どういうデータがあり、どういう結果が得たいのか」をできるだけ詳細に書いてください。また、データはDataFrameのprint結果のコピペではなく、CSVに書かれているテキストを載せた方が回答する側としてはありがたいです。
kak

2019/04/18 01:35

ご指摘ありがとうございます。確かに自分で読み返してもよく分からない内容でした。 失礼しました。質問内容を修正しながらプログラムを見直し、目的は達成できたように思います。 ですが、もし見ていただけるなら改善点や他の方法を教えてください。
guest

回答1

0

ベストアンサー

  • 仕様がわからない

df_test_id等いくつかの変数が、未定義のまま使用されています。

test*.csvが270個あります
270個のsample.csv

→testなのかsampleなのか?
→270個と仰っていますが、sample1890.csvと1890個ありそうなファイル名ですし、プログラム上も1890ファイル処理しているようです。

一つのCSVファイル中でindex2~1890

→プログラム上では270行までしか処理していないようです。

  • ループ内でファイル出力

ファイル操作は基本的に重たい処理だと考えてください。しかし、プログラム2では最高1890*270回のファイル出力を行うかと思います。さらにプログラム1では10倍のファイル出力がありました。それは遅い筈です。
プログラム2では折角ループの外に結果データの宣言を移動したのですから、全てのデータを読み終わってループを抜けてから出力しましょう。

  • ループ内でconcatしているとこ

df_frameはループ毎に値が増えていき、df_resultに連結されていきます。次ループの時、既に入っている値を再度入れてしまうことになります。
つまりは以下のような処理が行われています。

import pandas as pd df_result = pd.DataFrame() df_frame = pd.DataFrame([1])# 1行目が入ってる # ループ1回目 df_frame = df_frame.append([2])# 2行目 df_result = pd.concat([df_result,df_frame]) print(df_result) ''' 0 0 1 0 2 ''' # ループ2回目 df_frame = df_frame.append([3])# 2行目 df_result = pd.concat([df_result,df_frame]) print(df_result) ''' 0 0 1 0 2 0 1 0 2 0 3 '''

まずファイル毎の結果をdf_frameに格納していきます。その後、"内側のループが終わった後"にdf_resultに連結してあげたらいいと思います。
ループ内の処理は最小限にするのが基本です。

投稿2019/04/19 05:47

moredeep

総合スコア1507

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

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

kak

2019/04/23 12:32

遅くなりました。ファイルが消えてしまったので少ないサンプルで作り直してプログラムを修正しました。printで途中経過を見ていた内容がまさにご指摘いただいた通りでした。お陰様でかなりスピードアップ出来ました。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問