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

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

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

bash(Bourne-again-Shell)は sh(Bourne Shell)のインプリメンテーションに様々な機能が追加されたシェルです。LinuxやMac OS XではBashはデフォルトで導入されています。

CSV

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

Python 3.x

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

Python

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

pandas

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

Q&A

解決済

2回答

4470閲覧

pythonでbashのdiffコマンドを実現したい

IST

総合スコア14

bash

bash(Bourne-again-Shell)は sh(Bourne Shell)のインプリメンテーションに様々な機能が追加されたシェルです。LinuxやMac OS XではBashはデフォルトで導入されています。

CSV

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

Python 3.x

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

Python

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

pandas

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

0グッド

0クリップ

投稿2019/02/24 05:22

概要

CSVファイルA/B間のファイル差分をpythonで作成したツールで標準画面出力する

背景

pythonの学習を始め、CSVファイルの操作でつまづいている。

前提

学習に使用してしている環境は以下

  • python3.7
  • Anaconda
    • Pandas
  • Jupyter Note

郵便局のken_all.csvの形式を使用を想定して以下のようなデータを用意する

before.csv

bash

1mkdir /tmp/ken_all 2cd /tmp/ken_all 3vim before.txt

csv

113101,"100 ","1000000","トウキョウト","チヨダク","イカニケイサイガナイバアイ","東京都","千代田区","以下に掲載がない場合",0,0,0,0,0,0 213101,"102 ","1020072","トウキョウト","チヨダク","イイダバシ","東京都","千代田区","飯田橋",0,0,1,0,0,0 313101,"101 ","1010032","トウキョウト","チヨダク","イワモトチョウ","東京都","千代田区","岩本町",0,0,1,0,0,0 413101,"101 ","1010047","トウキョウト","チヨダク","ウチカンダ","東京都","千代田区","内神田",0,0,1,0,0,0

after.csv

bash

1vim after.csv

csv

113101,"100 ","1000000","トウキョウト","チヨダク","イカニケイサイガナイバアイ","東京都","千代田区","以下に掲載がない場合",0,0,0,0,0,0 213101,"102 ","1020082","トウキョウト","チヨダク","イチバンチョウ","東京都","千代田区","一番町",0,0,0,0,0,0 313101,"101 ","1010035","トウキョウト","チヨダク","イワモトチョウ","東京都","千代田区","岩本町",0,0,1,0,0,0 413101,"101 ","1010047","トウキョウト","チヨダク","ウチカンダ","東京都","千代田区","内神田",0,0,1,0,0,5

diff

ファイルの差分を確認

bash

1diff before.txt after.txt

diff

12,4c2,4 2< 13101,"102 ","1020072","トウキョウト","チヨダク","イイダバシ","東京都","千代田区","飯田橋",0,0,1,0,0,0 3< 13101,"101 ","1010032","トウキョウト","チヨダク","イワモトチョウ","東京都","千代田区","岩本町",0,0,1,0,0,0 4< 13101,"101 ","1010047","トウキョウト","チヨダク","ウチカンダ","東京都","千代田区","内神田",0,0,1,0,0,0 5--- 6> 13101,"102 ","1020082","トウキョウト","チヨダク","イチバンチョウ","東京都","千代田区","一番町",0,0,0,0,0,0 7> 13101,"101 ","1010035","トウキョウト","チヨダク","イワモトチョウ","東京都","千代田区","岩本町",0,0,1,0,0,0 8> 13101,"101 ","1010047","トウキョウト","チヨダク","ウチカンダ","東京都","千代田区","内神田",0,0,1,0,0,5

ゴール

目指す出力形式は以下

bash

1python3 diff_csv.py

diff

1-13101,"102 ","1020072","トウキョウト","チヨダク","イイダバシ","東京都","千代田区","飯田橋",0,0,1,0,0,0 2+13101,"102 ","1020082","トウキョウト","チヨダク","イチバンチョウ","東京都","千代田区","一番町",0,0,0,0,0,0 3-13101,"101 ","1010032","トウキョウト","チヨダク","イワモトチョウ","東京都","千代田区","岩本町",0,0,1,0,0,0 4+13101,"101 ","1010035","トウキョウト","チヨダク","イワモトチョウ","東京都","千代田区","岩本町",0,0,1,0,0,0 5-13101,"101 ","1010047","トウキョウト","チヨダク","ウチカンダ","東京都","千代田区","内神田",0,0,1,0,0,0 6+13101,"101 ","1010047","トウキョウト","チヨダク","ウチカンダ","東京都","千代田区","内神田",0,0,1,0,0,5

備考

  • 理想に近いものはgit diffの出力形式
    • この結果を半角カナの順にソートしてあるものをイメージしている

diff

1@@ -1,4 +1,4 @@ 2 13101,"100 ","1000000","トウキョウト","チヨダク","イカニケイサイガナイバアイ","東京都","千代田区","以下に掲載がない場合",0,0,0,0,0,0 3-13101,"102 ","1020072","トウキョウト","チヨダク","イイダバシ","東京都","千代田区","飯田橋",0,0,1,0,0,0 4-13101,"101 ","1010032","トウキョウト","チヨダク","イワモトチョウ","東京都","千代田区","岩本町",0,0,1,0,0,0 5-13101,"101 ","1010047","トウキョウト","チヨダク","ウチカンダ","東京都","千代田区","内神田",0,0,1,0,0,0 6+13101,"102 ","1020082","トウキョウト","チヨダク","イチバンチョウ","東京都","千代田区","一番町",0,0,0,0,0,0 7+13101,"101 ","1010035","トウキョウト","チヨダク","イワモトチョウ","東京都","千代田区","岩本町",0,0,1,0,0,0 8+13101,"101 ","1010047","トウキョウト","チヨダク","ウチカンダ","東京都","千代田区","内神田",0,0,1,0,0,5

手順

python

1import pandas as pd 2file1 = '/tmp/ken_all/before.csv' 3file2 = '/tmp/ken_all/after.csv' 4data1 = pd.read_csv(file1, encoding="shift_jis") 5data2 = pd.read_csv(file2, encoding="shift_jis")

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

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

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

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

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

guest

回答2

0

ベストアンサー

git diff コマンドが理想に近いのであれば、それを Python 経由で実行した結果を使えばいいのではないでしょうか?

python

1import subprocess 2 3# コマンドを実行し、結果を受け取る。 4command = 'git diff before.csv after.csv' 5ret = subprocess.run(command.split(), stdout=subprocess.PIPE) 6output = result.stdout.decode() 7 8# 受け取った結果を行ごとにリストにする。 9lines = output.splitlines() 10 11# 確認 12for i, line in enumerate(lines): 13 print(i, line)
0 diff --git a/before.csv b/after.csv 1 index 9e4b895..dc56adb 100644 2 --- a/before.csv 3 +++ b/after.csv 4 @@ -1,4 +1,4 @@ 5 13101,"100 ","1000000","トウキョウト","チヨダク","イカニケイサイガナイバアイ","東京都","千代田区","以下に掲載がない場合",0,0,0,0,0,0 6 -13101,"102 ","1020072","トウキョウト","チヨダク","イイダバシ","東京都","千代田区","飯田橋",0,0,1,0,0,0 7 -13101,"101 ","1010032","トウキョウト","チヨダク","イワモトチョウ","東京都","千代田区","岩本町",0,0,1,0,0,0 8 -13101,"101 ","1010047","トウキョウト","チヨダク","ウチカンダ","東京都","千代田区","内神田",0,0,1,0,0,0 9 \ No newline at end of file 10 +13101,"102 ","1020082","トウキョウト","チヨダク","イチバンチョウ","東京都","千代田区","一番町",0,0,0,0,0,0 11 +13101,"101 ","1010035","トウキョウト","チヨダク","イワモトチョウ","東京都","千代田区","岩本町",0,0,1,0,0,0 12 +13101,"101 ","1010047","トウキョウト","チヨダク","ウチカンダ","東京都","千代田区","内神田",0,0,1,0,0,5 13 \ No newline at end of file

追記

pandas だけで同じような出力をするなら以下のようになります。

  1. 一致しない行を抽出する。
  2. 一致しない行を交互にマージする。

python

1import csv 2from io import StringIO 3 4import pandas as pd 5 6# CSV を読み込む 7before = pd.read_csv('before.txt', header=None) 8after = pd.read_csv('after.txt', header=None) 9 10# 左結合 11diff_before = before.merge(after, indicator=True, how='left').loc[lambda x : x['_merge'] != 'both'] 12diff_after = after.merge(before, indicator=True, how='left').loc[lambda x : x['_merge'] != 'both'] 13 14# マーカー挿入 15diff_before.insert(0, 'marker', '-') 16diff_after.insert(0, 'marker', '+') 17 18# 交互に結合する。 19diff = pd.concat([diff_before, diff_after]).sort_index(kind='merge') 20# _merge 列を削除 21diff.drop(columns=['_merge'], inplace=True) 22 23# DataFrame を出力する。 24ofs = StringIO() 25diff.to_csv(ofs, index=False, header=False) 26output = ofs.getvalue() 27 28print(output)

python

1-,13101,102,1020072,トウキョウト,チヨダク,イイダバシ,東京都,千代田区,飯田橋,0,0,1,0,0,0 2+,13101,102,1020082,トウキョウト,チヨダク,イチバンチョウ,東京都,千代田区,一番町,0,0,0,0,0,0 3-,13101,101,1010032,トウキョウト,チヨダク,イワモトチョウ,東京都,千代田区,岩本町,0,0,1,0,0,0 4+,13101,101,1010035,トウキョウト,チヨダク,イワモトチョウ,東京都,千代田区,岩本町,0,0,1,0,0,0 5-,13101,101,1010047,トウキョウト,チヨダク,ウチカンダ,東京都,千代田区,内神田,0,0,1,0,0,0 6+,13101,101,1010047,トウキョウト,チヨダク,ウチカンダ,東京都,千代田区,内神田,0,0,1,0,0,5

投稿2019/02/24 08:22

編集2019/02/25 03:16
tiitoi

総合スコア21956

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

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

wwbQzhMkhhgEmhU

2019/02/24 18:36 編集

→ tiitoiさんへ pandas利用の際の差異抽出は行数が違うだけでアウトですよ。 前提として、 ・同じ行がない ・順番は気にしない が必要ですが、左結合でmergeしたもののうち同一でないものを選択する方法を左右でやれば抽出できそうです。 https://stackoverflow.com/questions/48647534/python-pandas-find-difference-between-two-data-frames まぁ、前提によりdiffの出力とは違ってしまいますが...
tiitoi

2019/02/25 03:18

ご指摘ありがとうございます。確かに単純比較だと各行が1対1対応している前提になるので、よくないですね。 紹介いただいた方法で修正してみました。
wwbQzhMkhhgEmhU

2019/02/25 03:27

動かしていませんが、目視でコード確認しました。大丈夫かと。 私が言っていいのか分かりませんが、対応ありがとうございます。
IST

2019/02/28 14:25

お二人にベストアンサーを付けたいですが、 修正も含めてご対応を頂いたこともありtiitoi様にベストアンサーをつけさせて頂きたいと思います。 ありがとうございました!!
guest

0

tiitoiさん
コメントありがとうございます。
この度は、pythonを利用してツールを作成することでpython/Pandasの学習がしたいと考えております。
そのため、シェルを実行する方法も素敵ですがどちらかというと、pythonで完結させたいです。

投稿2019/02/24 08:28

IST

総合スコア14

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

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

tiitoi

2019/02/24 08:32

回答に対するコメントは回答のコメント欄をご活用ください。 git diff ライクな結果というのは理解しているのですが、最終的に求める出力というのを記載いただいた2つのCSVの例でよいので、手動で作成して質問欄に記載いただけますか? あと「半角カナの順」というのは、どの列を半角カナの順にソートした結果について言ってますでしょうか?
IST

2019/02/24 08:40

質問欄のゴールに記載している6行が目指している出力になります。 Pythonファイルを実行したら、 記載しているような出力が得られることがゴールとなります。 半角カナのソートについては、 変更のあった行が大きなブロックになってしまうと見づらくなってしまうので、変更前の行の直後に変更後の結果行が来る、という表示にできたらベストだと考えています。
tiitoi

2019/02/24 09:22

pandas でやる方法を追記しました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問