現状
2つのcsvファイルを比較し、差異のある行を確認したいと考えており、
excelのマクロで比較処理をかけてみましたが、
1時間たっても終わらず、今現在も処理中です。
※これを書いている間に、 応答なしでExcelがフリーズしておりました。
ファイル内部の状態
・1列目から100列目まで比較元のデータが入っている。
・101列目から201列目まで比較先のデータが入っている。
・データは比較先・比較元各々で約170000行存在します。
・各セルのデータは日付・最大8桁の数値・任意の文字列、空のセルと複数存在する。
マクロ内容
Option Explicit
Sub 2019_cros()
Dim X As Long
Dim Y As Long
Dim Z1 As Long
Application.ScreenUpdating = False
X = 2
Y = 1
Z1 = 2
Do Until Cells(X, Y) = "" '比較元が空白である事を確認したら全処理を止める
'比較元を左、比較先を右とする。
If Cells(X, Y + 1) = Cells(Z1, Y + 110) And Cells(X, Y + 2) = Cells(Z1, Y + 111) And Cells(X, Y + 3) = Cells(Z1, Y + 112) And Cells(X, Y + 4) = Cells(Z1, Y + 113) And Cells(X, Y + 5) = Cells(Z1, Y + 114) And Cells(X, Y + 6) = Cells(Z1, Y + 115) And _
Cells(X, Y + 7) = Cells(Z1, Y + 116) And Cells(X, Y + 8) = Cells(Z1, Y + 117) And Cells(X, Y + 9) = Cells(Z1, Y + 118) And Cells(X, Y + 10) = Cells(Z1, Y + 119) And Cells(X, Y + 11) = Cells(Z1, Y + 120) And Cells(X, Y + 12) = Cells(Z1, Y + 121) And _
Cells(X, Y + 13) = Cells(Z1, Y + 122) And Cells(X, Y + 14) = Cells(Z1, Y + 123) And Cells(X, Y + 15) = Cells(Z1, Y + 124) And Cells(X, Y + 16) = Cells(Z1, Y + 125) And Cells(X, Y + 17) = Cells(Z1, Y + 126) And Cells(X, Y + 18) = Cells(Z1, Y + 127) And _
Cells(X, Y + 19) = Cells(Z1, Y + 128) And Cells(X, Y + 20) = Cells(Z1, Y + 129) And Cells(X, Y + 21) = Cells(Z1, Y + 130) And Cells(X, Y + 22) = Cells(Z1, Y + 131) And Cells(X, Y + 23) = Cells(Z1, Y + 132) And Cells(X, Y + 24) = Cells(Z1, Y + 133) And _
Cells(X, Y + 25) = Cells(Z1, Y + 134) And Cells(X, Y + 26) = Cells(Z1, Y + 135) And Cells(X, Y + 27) = Cells(Z1, Y + 136) And Cells(X, Y + 28) = Cells(Z1, Y + 137) And Cells(X, Y + 29) = Cells(Z1, Y + 138) And Cells(X, Y + 30) = Cells(Z1, Y + 139) And _
Cells(X, Y + 31) = Cells(Z1, Y + 140) And Cells(X, Y + 32) = Cells(Z1, Y + 141) And Cells(X, Y + 33) = Cells(Z1, Y + 142) And Cells(X, Y + 34) = Cells(Z1, Y + 143) And Cells(X, Y + 35) = Cells(Z1, Y + 144) And Cells(X, Y + 36) = Cells(Z1, Y + 145) And _
Cells(X, Y + 37) = Cells(Z1, Y + 146) And Cells(X, Y + 38) = Cells(Z1, Y + 147) And Cells(X, Y + 39) = Cells(Z1, Y + 148) And Cells(X, Y + 40) = Cells(Z1, Y + 149) And Cells(X, Y + 41) = Cells(Z1, Y + 150) And Cells(X, Y + 42) = Cells(Z1, Y + 151) And _
Cells(X, Y + 43) = Cells(Z1, Y + 152) And Cells(X, Y + 44) = Cells(Z1, Y + 153) And Cells(X, Y + 45) = Cells(Z1, Y + 154) And Cells(X, Y + 46) = Cells(Z1, Y + 155) And Cells(X, Y + 47) = Cells(Z1, Y + 156) And Cells(X, Y + 48) = Cells(Z1, Y + 157) And _
Cells(X, Y + 49) = Cells(Z1, Y + 158) And Cells(X, Y + 50) = Cells(Z1, Y + 159) And Cells(X, Y + 51) = Cells(Z1, Y + 160) And Cells(X, Y + 52) = Cells(Z1, Y + 161) And Cells(X, Y + 53) = Cells(Z1, Y + 162) And Cells(X, Y + 54) = Cells(Z1, Y + 163) And _
Cells(X, Y + 55) = Cells(Z1, Y + 164) And Cells(X, Y + 56) = Cells(Z1, Y + 165) And Cells(X, Y + 57) = Cells(Z1, Y + 166) And Cells(X, Y + 58) = Cells(Z1, Y + 167) And Cells(X, Y + 59) = Cells(Z1, Y + 168) And Cells(X, Y + 60) = Cells(Z1, Y + 169) And _
Cells(X, Y + 61) = Cells(Z1, Y + 170) And Cells(X, Y + 62) = Cells(Z1, Y + 171) And Cells(X, Y + 63) = Cells(Z1, Y + 172) And Cells(X, Y + 64) = Cells(Z1, Y + 173) And Cells(X, Y + 65) = Cells(Z1, Y + 174) And Cells(X, Y + 66) = Cells(Z1, Y + 175) And _
Cells(X, Y + 67) = Cells(Z1, Y + 176) And Cells(X, Y + 68) = Cells(Z1, Y + 177) And Cells(X, Y + 69) = Cells(Z1, Y + 178) And Cells(X, Y + 70) = Cells(Z1, Y + 179) And Cells(X, Y + 71) = Cells(Z1, Y + 180) And Cells(X, Y + 72) = Cells(Z1, Y + 181) And _
Cells(X, Y + 73) = Cells(Z1, Y + 182) And Cells(X, Y + 74) = Cells(Z1, Y + 183) And Cells(X, Y + 75) = Cells(Z1, Y + 184) And Cells(X, Y + 76) = Cells(Z1, Y + 185) And Cells(X, Y + 77) = Cells(Z1, Y + 186) And Cells(X, Y + 78) = Cells(Z1, Y + 187) And _
Cells(X, Y + 79) = Cells(Z1, Y + 188) And Cells(X, Y + 80) = Cells(Z1, Y + 189) And Cells(X, Y + 81) = Cells(Z1, Y + 190) And Cells(X, Y + 82) = Cells(Z1, Y + 191) And Cells(X, Y + 83) = Cells(Z1, Y + 192) And Cells(X, Y + 84) = Cells(Z1, Y + 193) And _
Cells(X, Y + 85) = Cells(Z1, Y + 194) And Cells(X, Y + 86) = Cells(Z1, Y + 195) And Cells(X, Y + 87) = Cells(Z1, Y + 196) And Cells(X, Y + 88) = Cells(Z1, Y + 197) And Cells(X, Y + 89) = Cells(Z1, Y + 198) And Cells(X, Y + 90) = Cells(Z1, Y + 199) And _
Cells(X, Y + 91) = Cells(Z1, Y + 200) And Cells(X, Y + 92) = Cells(Z1, Y + 201) And Cells(X, Y + 93) = Cells(Z1, Y + 202) And Cells(X, Y + 94) = Cells(Z1, Y + 203) And Cells(X, Y + 95) = Cells(Z1, Y + 204) And Cells(X, Y + 96) = Cells(Z1, Y + 205) And _
Cells(X, Y + 97) = Cells(Z1, Y + 206) And Cells(X, Y + 98) = Cells(Z1, Y + 207) And Cells(X, Y + 99) = Cells(Z1, Y + 208) And Cells(X, Y + 100) = Cells(Z1, Y + 209) And Cells(X, Y + 101) = Cells(Z1, Y + 210) And Cells(X, Y + 102) = Cells(Z1, Y + 211) And _
Cells(X, Y + 103) = Cells(Z1, Y + 212) And Cells(X, Y + 104) = Cells(Z1, Y + 213) And Cells(X, Y + 105) = Cells(Z1, Y + 214) And Cells(X, Y + 106) = Cells(Z1, Y + 215) And Cells(X, Y + 107) = Cells(Z1, Y + 216) And Cells(X, Y + 108) = Cells(Z1, Y + 217) Then
Range(Cells(X, Y), Cells(X, Y + 108)).Interior.ColorIndex = 45
Range(Cells(Z1, Y + 110), Cells(Z1, Y + 217)).Interior.ColorIndex = 42
'全セルが一致したので比較元にオレンジ、比較先に水色を塗る
X = X + 1
Z1 = 2
ElseIf Cells(Z1, Y + 110) = "" Then
X = X + 1
Z1 = 2
Else
Z1 = Z1 + 1
End If
Loop
配列変数を組んで入れていけば何とかなるのではないかと思いながら、
組むことができず、取り急ぎで組んだものです。
比較データをどう使うか
差異のあるデータ・片方にしか存在しないデータを元に、ここには登場しない別のcsvファイルを点検修正する予定です。
教えていただきたい事
・データの数的にマクロで比較する事が現実的かどうか。
(そもそも上記マクロがひどい内容だという事は重々承知しておりますが、書き直す時間なかなか取れず、件数の少ない別のcsvファイル間で処理ができ、最後に残ったこの大きなファイルに困っております。)
・Excel以外で同様の処理を行う方法はありますでしょうか?
以上となります。どなたかお知恵を拝借できないでしょうか?
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
- メールアドレスの認証
メールアドレスの認証
- 質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
+2
・データの数的にマクロで比較する事が現実的かどうか。
(そもそも上記マクロがひどい内容だという事は重々承知しておりますが、書き直す時間なかなか取れず、件数の少ない別のcsvファイル間で処理ができ、最後に残ったこの大きなファイルに困っております。)
難しくはないと思うのですが件数が多い&条件が複数ある(というか多すぎる)ので時間がかかるのは仕方ないように思えます。
条件はすべてAndのようですので条件部分を書き直すといくらか時間が短縮される&処理が軽くなるかもしれません。
ちなみに私なら比較元が空白である事を確認したら全処理を止める記述のあとに
以下のように先に全セルが一致するか判定し、その判定結果をさらに判定するようにします。
Dim i As Long
Dim j As Long
i = 1
j = 110
Dim flg As Boolean
flg = True
' すべて同じなのか先に判定してしまう。
Do While flg
'比較元を左、比較先を右とする。
If Cells(X, Y + i) = Cells(Z1, Y + j) Then
' 比較元と比較先が同じ場合
' 隣の列に移動
i = i + 1
j = j + 1
'iが109になった場合は処理を抜ける
If i = 109 Then
Exit Do
End If
Else
' 比較元と比較先が同じではない場合
flg = False
End If
Loop
flgがfalseになった場合は全セルが一致しなかった、ということになります。
たくさん書いたIf文の条件はこのflgに置き換えれば良いと思います。
・Excel以外で同様の処理を行う方法はありますでしょうか?
差分を比較するツール(例えばWinMergeとか)を使えば差分の確認だけならできます。
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+2
これは明らかにawkの得意分野ですね。windowsでは馴染みが薄いかもしれませんが、今は簡単に使えるようにできます。
次に以下のような感じのスクリプトをテキストエディタで書いてたとえばtest.awkというテキストファイルにセーブします。
BEGIN{FS=","; n=100}
{
for(i=1; i<=n; i++){
x=$i; y=$(i+n);
if(x!=y){
printf "line %d: col %d = '%s'; col %d = '%s'\n", NR, i, x, i+n, y;
}
}
}
上記に従えばawk -f test.awk 対象ファイル
とコマンドを入力すると値の不一致なデータとその行・列番号が出力されるはずです。
入力元ファイルはCSVファイルにコンバートしてあるものとこのコードは仮定していますが、本来はtab区切りデータを推奨したいところです。
やってみないと分かりませんが、たぶんvbaよりは速く結果が返ってくるんじゃないかなと思います。慣れればVBAなんてバカバカしくて使ってられなくなる…はず。
gnu awk4 on windows
さらに調べてみたところ、https://www.klabaster.com/freeware.htmで、gawk4.0のwindows版実行ファイルが配布されています。
gawk4.0にはFPATという組み込み変数が追加されており、「値の中に,が含まれるcsvを扱おうとすると困ってしまう」問題を実質的に解決できるようになっています。
参考:GNU AWKでCSVファイルを楽々あつかう組込変数FPATと、関数のインダイレクト呼び出し
ダウンロードしてexeファイルをpathの通ったところに置くだけですので、導入の簡単さではbusyboxと変わらず、機能面を考えるとこちらが良いでしょう。
これを利用して上記スクリプトを書き換えたものを示しておきます。
BEGIN{FPAT="([^,]+)|(\"[^\"]+\")"; n=100}
{
for(i=1; i<=n; i++){
x=$i; y=$(i+n);
if(x!=y){
printf "line %d: col %d = '%s'; col %d = '%s'\n", NR, i, x, i+n, y;
}
}
}
追記: 上記サイトから引用します。
このパターンでは、CSVファイルの規格にある「ダブルクォートで括られた中に改行を含めることが可能」というルールに対応することはできません。
このような中途半端な状態なのにCSVファイルを扱えると明言するのはおかしいのではないかという意見もありますが、gawkの開発は「完全を目指すのではなく9割をサクサクこなし、フィールドに改行を含むようなCSVファイルは専用のツールで処理すれば良い」という思想で進められました。
ようするに、いつでも使えるわけではないが、使えるときには使って簡単に片づけたらいいじゃんという発想です。awkとはそういうものです。awkが本件ではうまく使えない可能性はあるし、もっといい方法がある可能性もあります。
私はこれを唯一絶対最高の解決策だと主張したいわけではありません。しかし、条件が合うなら最短距離で問題を片づけられる可能性はあると考えています。何かごちゃごちゃ言っている人がいますが、まどわされず、ご自分の案件に使えるかどうかは質問者さんご自身が淡々と判断していただければと思います。
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+1
VBAでやるような処理ではないと思いますが、100セルが全て同じかどうかしか見ていないようですし、csvファイルといっても両ファイルの出力形式が同じなら、ファイルのテキスト比較でも要件を満たすのではないですか?
片方の行抜けは想定せず、同一行同士のテキスト比較しかしないのであれば、VBAでも容易に書くことはできます。
Open "比較元csvファイル名" For Input As #1
Open "比較先csvファイル名" For Input As #2
Do Until EOF(1)
Line Input #1, hoge1
If Not EOF(2) Then
Line Input #2, hoge2
Else
hoge2 = ""
End If
If hoge1 <> hoge2 Then
'ここに不一致時の処理を書く
End If
Loop
Close #1
Close #2
とはいえ、安易すぎるコードかもしれません。
投稿
score 332
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+1
何か音沙汰がないし、質問者さんは他のやり方も模索してるとのことであり、また質問者さんのマクロを配列にしたバージョンを誰も作ってないので、awk方式ではカンマ付き数字あるだけで終わるし、いろいろ考慮した結果、回答することにしました。
■サンプルデータ作成用powershell
$fixedRow= New-Object PSObject
$fixedRow | Add-Member -MemberType NoteProperty -Name "dummy" -Value 'ダミー'
$colCount=109
$rowCount=17000
foreach($pat in @("left", "right")) {
for ($col=0; $col -lt $colCount; $col++) {
$fixedRow | Add-Member -MemberType NoteProperty -Name ($pat+($col+1)) -Value (([string]$col) + ",000")
}
}
@(for ($row = 0; $row -lt $rowCount; ++$row) {
$fixedRow
}) | ConvertTo-Csv -NoTypeInformation | select -Skip 1 | Out-File -Encoding Default data.csv
最左列をダミー、次の109列分のデータが左側、次の109列分のデータを右側として、17000行(1/10サイズ)のデータをdata.csvに作成している。ファイルサイズで32MB程度。
これをcreate_data.ps1とした場合、
powershell -ExecutionPolicy RemoteSigned -File create_data.ps1
とかで実行できるはず。
■CSV左右比較同一行削除フィルタpowershell
$header=New-Object System.Collections.ArrayList
#$leftColName=New-Object System.Collections.ArrayList
#$rightColName=New-Object System.Collections.ArrayList
$header.add('dummy') > $null
$colCount=109
$left = "left"
$right = "right"
foreach($colPrefix in @($left, $right)) {
for ($i = 0; $i -lt $colCount; ++$i) {
$header.add($colPrefix + $i) > $null
}
}
# 汎用コード(A)...遅いので未使用
#for ($i = 0; $i -lt $colCount; ++$i) {
# $leftColName.Add($left+$i) > $null
# $rightColName.Add($right+$i) > $null
#}
Import-Csv -Encoding default -Path '.\data.csv' -Header $header |
where {
# 汎用コード(B)...遅いので未使用
#$result = $false
#for ($i = 0; $i -lt $colCount; ++$i) {
# $result = $result -or ($_.($leftColName[$i]) -ne $_.($rightColName[$i]))
#}
#$result;
$_.left0 -ne $_.right0 -or
$_.left1 -ne $_.right1 -or
$_.left2 -ne $_.right2 -or
$_.left3 -ne $_.right3 -or
$_.left4 -ne $_.right4 -or
$_.left5 -ne $_.right5 -or
$_.left6 -ne $_.right6 -or
$_.left7 -ne $_.right7 -or
$_.left8 -ne $_.right8 -or
$_.left9 -ne $_.right9 -or
$_.left10 -ne $_.right10 -or
$_.left11 -ne $_.right11 -or
$_.left12 -ne $_.right12 -or
$_.left13 -ne $_.right13 -or
$_.left14 -ne $_.right14 -or
$_.left15 -ne $_.right15 -or
$_.left16 -ne $_.right16 -or
$_.left17 -ne $_.right17 -or
$_.left18 -ne $_.right18 -or
$_.left19 -ne $_.right19 -or
$_.left20 -ne $_.right20 -or
$_.left21 -ne $_.right21 -or
$_.left22 -ne $_.right22 -or
$_.left23 -ne $_.right23 -or
$_.left24 -ne $_.right24 -or
$_.left25 -ne $_.right25 -or
$_.left26 -ne $_.right26 -or
$_.left27 -ne $_.right27 -or
$_.left28 -ne $_.right28 -or
$_.left29 -ne $_.right29 -or
$_.left30 -ne $_.right30 -or
$_.left31 -ne $_.right31 -or
$_.left32 -ne $_.right32 -or
$_.left33 -ne $_.right33 -or
$_.left34 -ne $_.right34 -or
$_.left35 -ne $_.right35 -or
$_.left36 -ne $_.right36 -or
$_.left37 -ne $_.right37 -or
$_.left38 -ne $_.right38 -or
$_.left39 -ne $_.right39 -or
$_.left40 -ne $_.right40 -or
$_.left41 -ne $_.right41 -or
$_.left42 -ne $_.right42 -or
$_.left43 -ne $_.right43 -or
$_.left44 -ne $_.right44 -or
$_.left45 -ne $_.right45 -or
$_.left46 -ne $_.right46 -or
$_.left47 -ne $_.right47 -or
$_.left48 -ne $_.right48 -or
$_.left49 -ne $_.right49 -or
$_.left50 -ne $_.right50 -or
$_.left51 -ne $_.right51 -or
$_.left52 -ne $_.right52 -or
$_.left53 -ne $_.right53 -or
$_.left54 -ne $_.right54 -or
$_.left55 -ne $_.right55 -or
$_.left56 -ne $_.right56 -or
$_.left57 -ne $_.right57 -or
$_.left58 -ne $_.right58 -or
$_.left59 -ne $_.right59 -or
$_.left60 -ne $_.right60 -or
$_.left61 -ne $_.right61 -or
$_.left62 -ne $_.right62 -or
$_.left63 -ne $_.right63 -or
$_.left64 -ne $_.right64 -or
$_.left65 -ne $_.right65 -or
$_.left66 -ne $_.right66 -or
$_.left67 -ne $_.right67 -or
$_.left68 -ne $_.right68 -or
$_.left69 -ne $_.right69 -or
$_.left70 -ne $_.right70 -or
$_.left71 -ne $_.right71 -or
$_.left72 -ne $_.right72 -or
$_.left73 -ne $_.right73 -or
$_.left74 -ne $_.right74 -or
$_.left75 -ne $_.right75 -or
$_.left76 -ne $_.right76 -or
$_.left77 -ne $_.right77 -or
$_.left78 -ne $_.right78 -or
$_.left79 -ne $_.right79 -or
$_.left80 -ne $_.right80 -or
$_.left81 -ne $_.right81 -or
$_.left82 -ne $_.right82 -or
$_.left83 -ne $_.right83 -or
$_.left84 -ne $_.right84 -or
$_.left85 -ne $_.right85 -or
$_.left86 -ne $_.right86 -or
$_.left87 -ne $_.right87 -or
$_.left88 -ne $_.right88 -or
$_.left89 -ne $_.right89 -or
$_.left90 -ne $_.right90 -or
$_.left91 -ne $_.right91 -or
$_.left92 -ne $_.right92 -or
$_.left93 -ne $_.right93 -or
$_.left94 -ne $_.right94 -or
$_.left95 -ne $_.right95 -or
$_.left96 -ne $_.right96 -or
$_.left97 -ne $_.right97 -or
$_.left98 -ne $_.right98 -or
$_.left99 -ne $_.right99 -or
$_.left100 -ne $_.right100 -or
$_.left101 -ne $_.right101 -or
$_.left102 -ne $_.right102 -or
$_.left103 -ne $_.right103 -or
$_.left104 -ne $_.right104 -or
$_.left105 -ne $_.right105 -or
$_.left106 -ne $_.right106 -or
$_.left107 -ne $_.right107 -or
$_.left108 -ne $_.right108
} | ConvertTo-Csv -NoTypeInformation | select -Skip 1 | Out-File -Encoding Default diff.csv
data.csvを読んで左右を比較し、同一行はフィルタして、違ってるものをdiff.csvとして吐き出す。ぶっちゃけ遅い。
これをfilter_data.ps1とした場合、
powershell -ExecutionPolicy RemoteSigned -File filter_data.ps1
とかで実行できるはず。
■CSV左右比較同一行削除フィルタpython3スクリプト
import csv
target_file = 'data.csv'
diff_file = 'diff.csv'
encoding = 'cp932'
delimiter = ','
with open(target_file, 'r', encoding=encoding, newline='') as f:
reader = csv.reader(f, delimiter=delimiter)
with open(diff_file, 'w', encoding=encoding, newline='') as g:
writer = csv.writer(g, delimiter=delimiter)
offset = 1
count = 109
for row in reader:
result = False
for i in range(count):
result = result or (row[offset + i] != row[offset + count + i])
if result:
writer.writerow(row)
同じことをするpython3スクリプト。CSVのクォート仕様が最小限なので、出力は少し異なる。
実行にはpython3.Xが必要。これをdiff.pyとした場合、
python diff.py
で実行できる(環境によってはpythonでなくpython3。適宜読み替え)。
■読込形式と出力を揃えたawkスクリプト
BEGIN{FS=","; n=109}
{
is_diff = 0;
for(i=1; i<=n; i++){
x=$(i+1); y=$(i+n+1);
if(x!=y){
is_diff = 1;
break;
}
}
if (is_diff == 1) {
printf $0 "\n";
}
}
クォートを処理できないので、正しくparseできず、全てを異なる判定にしてしまう。動かしたければフィールド値にカンマを入れないように元データを修正しないとダメ。オススメは全くしないが、実行にはbusyboxを使いたいらしい。
これをdiff.awkとした場合、
busybox64.exe awk -f diff.awk data.csv > diff.csv
のように実行できる(インストールすると邪魔なファイルができるのでしてない)。
■1/10サイズの測定(32MB)
awk: 1,660ms
python: 1,647ms
powershell: 14,272ms
※ただしawk版は正しく処理できていない
※測定は繰り返し行い、最低値を使用(ディスクアクセスはキャッシュされたものが使われ、外部の影響も最小に)。
投稿
score 213
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 90.36%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
質問への追記・修正、ベストアンサー選択の依頼
Zuishin
2019/02/28 08:49
遅いとかいう話じゃなく、これ止まらないんじゃないですか?
やりたいことを日本語で説明してください。
うまく動かないものを元にして作ったものは動かないものにしかなりません。
NextSt
2019/02/28 16:56
お返事ありがとうございます。
If Cells(X, Y + 1) = Cells(Z1, Y + 110) And~~~の部分がもっと少ない(比較データももっと少ない)ファイルだと、
10分程で処理が済んでおりまして、動く…はずと思い条件部分を加工したものになります。
「1~100列(比較元)と、101列~201列(比較先)で、比較元と比較先のデータを1行ずつ比較し、内容が一致したものに色を付ける」
これを目的に組んだつもりです。
Zuishin
2019/02/28 18:54
データによっては終了すると思いますが、データによっては無限ループになると思います。
だから「このデータでうまくいったから」というのは当てになりません。
途中 Z1 がいきなり 2 に戻っているところや、(2, 2) から評価を始めていたり、101 でなく 110 と比較しているところなど、不明なところがあります。
NextSt
2019/03/01 11:50
ありがとうございます。
仰られている内容を確認し比較データの構成部分に追記が必要だとわかりましたので、補足を致します。
NextSt
2019/03/01 12:11
追記というよりコード自体修正が必要ですね。
If Cells(X, Y + 1) = Cells(Z1, Y + 101)…に修正して後に続くものも値も修正します。
これだと全部対象なしになってしまう…。
逆に前のファイルがなんでうまく処理されてたのかわからなくなってきました。
ご指摘ありがとうございます、コードを編集してみます。
Zuishin
2019/03/01 12:23
コードに修正は必要でしょうが、どのみちそれが意図した通り動くかどうかはわからないわけですよね?
これまでの回答が意図した動作になっているかどうかと、違っていれば数行のサンプルデータが必要ではないかと思います。