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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

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

pandas

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

Q&A

解決済

1回答

4447閲覧

Pandas Dataframe で column毎に indexを設定してグラフ化したい

Ruthird

総合スコア15

Python 3.x

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

pandas

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

0グッド

1クリップ

投稿2017/11/30 16:13

編集2017/12/01 17:16

###前提・実現したいこと

任意の波形を組み合わせて 比較分析する際、データの検索や表示がエクセルでは重くなりすぎて扱いづらく、
Python・Pandas で解決できないか考えています。

具体的には、
データフレーム形式になっている多数のcsvファイルの中から
1列ずつ読み込んで任意の組み合わせで別のデータフレームを組み上げ、
最後にpandasのプロット機能で1つのグラフにしたい。

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

現在は1つのファイルの中から 欲しいカラムを1つずつ数字入力で選択することで
必要なデータだけデータフレームに格納して グラフ化するところまで完成している。

読み込む多数のcsvファイルが現在はすべて同じindexの値・個数となっているので今は問題ないが、
今後はファイルによって異なるindexを持つ場合に対応した形にしたい。

【 追記 】
異なるindexの説明が不足していたので追記します。

例えば
csv_A index_A column_A1,A2,A3,・・・
csv_B index_B column_B1,B2,B3,・・・
という2つのファイルから欲しいカラムを合わせたデータフレームを作ると、

  df_A+B index_A+B column_A1,A2,B1,B2

のようになるとします。この状態でグラフ化すると index_A+B を すべてのカラムが参照することになってしまいますが、
A1,A2 は index_A を参照
B1,B2 は index_B を参照
するようにしたいのです。

実際のcsvファイルのindex_AとB は 実数の物理値で、
今扱っているデータだと Aのインデックス2つに対して Bのインデックスが1つとなっており、
しかも index_A2 (A2n) = index_B1 (Bn) のような関係でもあるので、
普通に結合して出来上がった データフレームは
colum_An で2個存在したのち、column_Bn の数値が1つ交互に格納されます。

このデータフレームをプロットすると以下のような状態になってしまいます。
column_An は 歯抜け        (3回に1回データが存在しない)
column_Bn は 前半のプロットがない (前半は3回に2回データが存在しないので 線にならない)
イメージ説明

このような問題に Pandas あるいは Dataframe に良い解法はありますでしょうか?

【 追記2 】

イメージですみませんが、それぞれの中身の一例を示します。
A~D : csv_A の 中身
F~I : csv_B の 中身
K~Q : df_A+B の 中身
K列 が index_A+B です。

今回の場合は index_A の 2個目と index_B の 1個目 が 完全同一のため index_A+B は

5,10,15,20,25,30,・・・

となりましたが、小数点以下が異なる場合、

5(A), 10(A), 10(B), 15(A), 20(A), 20(B), 25(A), 30(A), 30(B), ・・・

(A):元index_A、 (B):元index_B です。
のようになってしまうこともあります。

分かりづらくて申し訳ありません。

イメージ説明

###該当のソースコード

# -*- coding: utf-8 -*- import pandas as pd import matplotlib.pyplot as plt # 読み込む CSVファイル を選択して データフレーム化する df1 = pd.read_csv('sample1.csv', index_col=0) # 繰り返し処理内変数 を 定義する mode = 1 # 処理状態 wcount = 0 # 処理回数 paned = pd.Panel({}) # CSVから取得した データフレーム から 必要なデータのみ選択して # 空のデータフレーム に 記載・追記する 繰り返し処理 while mode > 0: # 処理回数をアップさせる wcount = wcount + 1 # 取得した CSV から グラフ化したい 列(カラム)を 1つずつ 数値入力する print('指定カラムは?') innum = int(input()) - 1 # カウントが1のときのみ、取得カラムのインデックスを 空のインデックスに入力する # これだとカウント2以降でインデックスが変わる場合に対応できないため、暫定処理 if wcount == 1: df2 = pd.DataFrame(index=[df1.index], columns=[]) print(df2) print('') else: pass # データフレームに 選択したカラムとバリューを入力する # データフレームの追加処理、左辺でカラム名を、右辺でカラム名を除いたバリューを記載する df2[df1.columns[innum]] = df1.values[:,int(innum)] # データフレームにカラム・バリューを追記する処理 から 抜けるか、 # もう1回カラム・バリューを追加するかを選択する print('終了? ⇒ 0 継続? ⇒ 1') inmode = int(input()) # 選択結果から モードの値 を書き換える # 現状は 同じ CSV から 別のカラムを指定する場合のみ # CSVファイルを変える、CSVファイルのディレクトリを変える、などの処理を追加のこと if inmode == 0: mode = 0 else: mode = 1 df2.plot() # # グラフタイトレイアウト plt.tight_layout() plt.savefig("sample.png") plt.show()

###試したこと

1つのカラムだけで1つのデータフレームにすればインデックスも任意にできるが、
この場合だと複数のデータフレームを持つことになり、1つのグラフにまとめて表示できなかった。

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

Python3.6、Pandas
Python歴2ヶ月で初質問のため、不作法などあるかもしれませんが ご容赦ください。

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

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

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

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

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

KojiDoi

2017/11/30 19:09

プログラムコードを示すときは、コードの前後の行に```を置いてください。特にpythonの場合インデントがちゃんと見えていないとチェックが困難です。
Ruthird

2017/11/30 23:57

大変失礼いたしました。ご指摘ありがとうございます。
KojiDoi

2017/12/01 16:43

すみませんが、追記された説明がサッパリ解りません。 csv_A, csv_B, df_A+B, index_A+B これらの実際の内容(一部でいいです)を示していただけませんか?
Ruthird

2017/12/01 17:17

一例を追記しました。お手数ですがご確認ください。
guest

回答1

0

ベストアンサー

とりあえず質問に挙げていただいたコードですが、カラム選択するたびにDataFrameに1列ずつ追加していくのではなく、選択されたカラム番号をリストに保持しておいて、最後にDataFrame.iloc() を使用してViewを生成すると、もう少しシンプルに記述できるかと思います。

こんな感じ

Pyton

1import pandas as pd 2import matplotlib.pyplot as plt 3 4# 読み込む CSVファイル を選択して データフレーム化する 5df1 = pd.read_csv('sample1.csv', index_col=0) 6 7selected_columns = [] 8while True: 9 # 取得した CSV から グラフ化したい 列(カラム)を 1つずつ 数値入力する 10 innum = int(input('指定カラムは?( 0 の場合は終了): ')) 11 12 # 終了の場合はデータを作成してループを抜ける 13 if innum == 0: 14 df2 = df1.iloc[:,selected_columns] 15 break; 16 17 # 選択されたインデックスをリストに追加 18 selected_columns.append(innum - 1) 19 20if not df2.empty: 21 df2.plot() 22 plt.tight_layout() 23 plt.savefig("sample.png") 24 plt.show()

次に質問にある複数ファイルから選択された列を結合する方法ですが、上記のループの外にもう一つファイル毎のループを作成する事になります。
で、ファイル毎で作成された新しいDataFrameは、順次リストに格納していき、最後にまとめて pandas.concat() を用いることで全てのDataFrameを結合することが出来ます。

この方法でしたら、各ファイル毎でIndex値に不整合があった場合でも問題ありません。データが無い箇所は NaNが入ることになります。

また、ファイルリストの作成ですが、globを使ってワイルドカードを使って指定する方法が簡単かと思います。

ということで、サンプルを書きましたので参考にしてください。

Python

1import pandas as pd 2import matplotlib.pyplot as plt 3import os 4import glob 5 6files = glob.glob('data/*.csv') 7dfs = [] 8for file in files: 9 basename = os.path.splitext(os.path.basename(file))[0] 10 df = pd.read_csv(file, index_col=0) 11 selected_columns = [] 12 while True: 13 print('FILE : {}'.format(basename)) 14 innum = int(input('指定カラムは?( 0 の場合は次ファイル): ')) 15 16 # 終了の場合はデータを作成してループを抜ける 17 if innum == 0: 18 dfs.append(df.iloc[:,selected_columns].copy()) 19 break; 20 21 # 選択されたインデックスをリストに追加 22 selected_columns.append(innum - 1) 23 24df2 = pd.concat(dfs, axis=1) 25# 以下省略

投稿2017/12/01 00:45

magichan

総合スコア15898

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

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

Ruthird

2017/12/01 16:37

ご回答ありがとうございます。 カラム番号だけ保持してシンプル化し、データフレームの結合機能を扱うと とても分かりやすくなるのですね。 ただ、自分の説明が不足しており、まだ解決には至っておりません。 本当にやりたかったことは 異なる index を 結合後の DataFrame でも参照できるようにすることです。 説明を追記してみましたので、もしこちらの内容で良きアイデアがあれば引き続きサポートをお願いします。
magichan

2017/12/02 03:21 編集

Pandasではデータの無いセルを dropna() で削除することができますので、dropna()を適用した後で、plot() すると良いのではないでしょうか。 ただ、df2 に dropna()を適用してしまうと、Nanを含む行全部を削除してしまうので、Column毎にループを回して、列単位で dropna().plot() を行ってみたらいかがでしょうか。 こんな感じ(__ は スペースに読み替えてください) ax = plt.show() for name,col in df2.iteritems(): __col.dropna().plot(ax=ax) plt.tight_layout() plt.savefig("sample.png")
Ruthird

2017/12/02 16:27 編集

おかげさまで意図したことが実現できましたので、 ベストアンサーにさせていただきました。 列単位 で dropna().plot() という考え方はかなり盲点でした。 こうすれば確かに index 自体が増えてしまっても 個々に plot できますね。 いろいろ参考にさせていただきます。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問