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

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

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

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

Q&A

解決済

3回答

4478閲覧

pythonで、2つのexcelファイルの差分(要素レベル)を抽出したい。

H.K2

総合スコア88

Python 3.x

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

0グッド

0クリップ

投稿2018/06/07 13:46

解決したいこと:
下記のような、2つのexcelファイルの差分を要素レベルで抽出し、変更の行、列を
{行数、列数}のような形でリストかデータフレームに格納したい
(あとで変更した要素の個所をopenpyxlなどで色を塗るため)

テーブル:
変更前excel例:
フェーズ 作業項目 担当者 計画工数 計画開始日 計画終了日 進捗率
要件定義 顧客A打合せ tanaka 3 2018/5/30 2018/6/1 100
基本設計 A機能基本設計 satou 15 2018/6/1 2018/6/4 20
基本設計 B機能基本、設計 yamada 12 2018/6/2 2018/6/8 30

変更後excel例:
フェーズ 作業項目 担当者 計画工数 計画開始日 計画終了日 進捗率
要件定義 顧客A打合せ tanaka 3 2018/5/30 2018/6/1 100
基本設計 A機能基本設計 satou 15 2018/6/1 2018/6/4 100
基本設計 C機能基本設計 yamada 18 2018/6/5 2018/6/12 10

やってみたこと:
下記のようなコードを描くと、行単位での抽出は可能でした。

import pandas as pd

df1 = pd.read_excel("before.xlsx")
df2 = pd.read_excel("after.xlsx")

df1['比較用の列'] = df1[['フェーズ', '作業項目', '担当者', '計画工数', '計画開始日', '計画終了日', '進捗率']].apply(lambda x: '{}{}{}{}{}{}{}'.format(x[0], x[1], x[2], x[3], x[4], x[5], x[6]), axis=1)
df2['比較用の列'] = df2[['フェーズ', '作業項目', '担当者', '計画工数', '計画開始日', '計画終了日', '進捗率']].apply(lambda x: '{}{}{}{}{}{}{}'.format(x[0], x[1], x[2], x[3], x[4], x[5], x[6]), axis=1)

df2[~df2['比較用の列'].isin(df1['比較用の列'])]

しかし、これだと変更後をベースにした行単位での差異は抽出可能ですが、
出来れば要素単位で抽出したいです。。
基本的な質問かもしれなくて申し訳ありませんが、ご教示いただけないでしょうか。

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

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

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

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

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

guest

回答3

0

書いてみました。

python

1import io 2import pandas as pd 3 4# 読み込み処理 5data1 = """ 6フェーズ 作業項目 担当者 計画工数 計画開始日 計画終了日 進捗率 7要件定義 顧客A打合せ tanaka 3 2018/5/30 2018/6/1 100 8基本設計 A機能基本設計 satou 15 2018/6/1 2018/6/4 20 9基本設計 B機能基本、設計 yamada 12 2018/6/2 2018/6/8 30 10""" 11 12data2 = """ 13フェーズ 作業項目 担当者 計画工数 計画開始日 計画終了日 進捗率 14要件定義 顧客A打合せ tanaka 3 2018/5/30 2018/6/1 100 15基本設計 A機能基本設計 satou 15 2018/6/1 2018/6/4 100 16基本設計 C機能基本設計 yamada 18 2018/6/5 2018/6/12 10 17""" 18 19df1 = pd.read_table(io.StringIO(data1), sep="\s+") 20df2 = pd.read_table(io.StringIO(data2), sep="\s+") 21 22print(df1) 23print(df2) 24""" => 25 フェーズ 作業項目 担当者 計画工数 計画開始日 計画終了日 進捗率 260 要件定義 顧客A打合せ tanaka 3 2018/5/30 2018/6/1 100 271 基本設計 A機能基本設計 satou 15 2018/6/1 2018/6/4 20 282 基本設計 B機能基本、設計 yamada 12 2018/6/2 2018/6/8 30 29 フェーズ 作業項目 担当者 計画工数 計画開始日 計画終了日 進捗率 300 要件定義 顧客A打合せ tanaka 3 2018/5/30 2018/6/1 100 311 基本設計 A機能基本設計 satou 15 2018/6/1 2018/6/4 100 322 基本設計 C機能基本設計 yamada 18 2018/6/5 2018/6/12 10 33""" 34 35# 違う場所のTFのdfを作る 36change_tf_df = df1 != df2 37print(change_tf_df) 38""" => 390 False False False False False False False 401 False False False False False False True 412 False True False True True True True 42""" 43 44# とりあえず愚直にfor(他にいいやり方があったら誰か教えてくだい・・・) 45lst = [] 46for i, row in change_tf_df.iterrows(): 47 for j, (_, v) in enumerate(row.iteritems()): 48 if v: 49 lst.append((i,j)) 50print(lst) 51""" => 52[(1, 6), (2, 1), (2, 3), (2, 4), (2, 5), (2, 6)] 53""" 54

投稿2018/06/09 06:56

hayataka2049

総合スコア30933

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

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

hayataka2049

2018/06/09 07:02

ありゃ、R.Shigemoriさんの回答のコメントを見たら、これじゃ駄目じゃん
H.K2

2018/06/09 11:20

ご回答ありがとうございました^^ ちょっと問題設定が悪かったっぽいですね???? なんとかこねくり回してみますー。 皆さんの意見をもとに工夫したら何とかできそうです。
guest

0

python

1import pandas as pd 2 3 4df01=pd.read_excel('before.xlsx',header=None) 5df02=pd.read_excel('before.xlsx',header=None) 6 7l=df01.values.tolist() 8r=df01.T.values.tolist() 9 10 11from pprint import pprint 12pprint(l),print() 13pprint(r)

間違えました。
データフレームだと、

import pandas as pd df01=pd.read_excel('before.xlsx',header=None) df02=pd.read_excel('before.xlsx',header=None)

投稿2018/06/09 00:44

編集2018/06/09 00:55
Untitled_Sample

総合スコア192

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

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

H.K2

2018/06/09 06:41

ご回答ありがとうございます。 l=df01.values.tolist() r=df01.T.values.tolist() とされているのは、rにdf01を転置したものをリスト化して、 どうされようとしているのでしょうか。 両方ともbefore.xlsxを読んできているので、afterとの差分がとられていないように思うのですが気のせいでしょうか。
Untitled_Sample

2018/06/09 09:14

勘違いでした。 一度、単純にリスト化して後で書き込めば良い思ってました。
H.K2

2018/06/09 11:18

わかりにくくて申し訳ありません^^ ご回答ありがとうございましたー。
guest

0

ベストアンサー

df1とdf2から比較したい行を抽出して比較演算をすると、全要素の比較結果がTrue,Falseの形式で返ってきます。

python3

1df1.iloc[抽出したい行番号,:]==df2.iloc[対応する行番号,:]

df1とdf2が完全に対応関係が一致しているのであれば、単純にdf1==df2とすると比較結果のDataFrameが得られるので、これを使ったほうが便利かもしれません

投稿2018/06/07 22:55

R.Shigemori

総合スコア3376

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

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

H.K2

2018/06/09 06:52

ご回答ありがとうございます。言葉足らずで申し訳ありません。 例えば、 [1,2,3 4,5,6 7,8,9]と [2,2,3, 4,5,6, 1,1,1, 7,9,9,] を比較した場合, 変更後ベースで1->2に、8->9に変更され、1,1,1が追加されたことを わかるようにしたいなあという目的があります。難しいでしょうか
R.Shigemori

2018/06/09 09:26

1,1,1の追加というのは、行の追加を意味しているのでしょうか?つまり、質問文の例示でいうと、変更後のexcelには4行目が追加になっているということでしょうか? とりあえず、上記の仮定が正しいのであれば、双方の列に共通するkeyが付与されているのであれば、このkeyの比較によって追加になった行を識別できると思います。仮にkeyがないようだと、行と行の間に追加になった場合はムリかと思います。 追加になった行が特定できれば、その行を除いて上記のようにDataFrame間を比較すれば、全ての要素の比較ができるようになります。
H.K2

2018/06/09 11:21

なるほど、keyとなる列がないのであればやっぱり難しいですか…。ありがとうございます。 keyとなる列を追加してもらえそうなので、そちらのほうを、依頼者に相談するかもしれません。 いろいろご相談に乗っていただきましたので、ベストアンサーとさせていただきます。 助かります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問