[[20250901080111]] 『データ件数が100万〜1000万件あるCSVファイルの編』(まっつわん) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) |

| 全文検索 | 過去ログ ]

 

『データ件数が100万〜1000万件あるCSVファイルの編集について』(まっつわん)

 データ件数が100万〜1000万件あるCSVファイルの編集をすることになりましたが、そのままではエクセルのシート上に展開できないので、どのような方法を使えばよいかアドバイスをください。

< 使用 Excel:Excel2021、使用 OS:Windows11 >


編集って何をするんですか?

ワークシートの行数と列数 1,048,576 行、16,384 列

というのがエクセルの制限なので、ざっと100万行ですね。
この制限を超えるサイズのデータをエクセルで扱うのには無理があるように思いますが。

どの程度の編集ができるのかは知りませんがEmEditorというのもあるようですが。
https://forest.watch.impress.co.jp/docs/topic/special/1590268.html

また、UNIX系のストリームエディター?とかそういうのも考えてみたらどうでしょうか?
特定の条件にあう行を抜き出したいならgrepとか?
あるいはawkとか?あるいはsedとか?

Windowsdでも使えるものをGNUが出してるんじゃないかな?(知らんけど)
(ゆたか) 2025/09/01(月) 08:50:09


 私の場合、普段からExcelとSQLite3を連携させているので、
 一旦、CSVを読み込みながら、SQLite3へインポートして、
 編集はSQLで行う、ですかね。

 SQLite3単独でも、csvのインポートができるので、Excelがいらないかも。

 編集がカラムに対し一括編集とか、特定の値に対し編集とかなら、SQLが楽ですね。
(tkit) 2025/09/01(月) 08:56:56

回答者の(まっつわん)さんですか。
(?????) 2025/09/01(月) 22:11:12

編集ってどんな感じなのかわかりませんが
私ならワードを使ってみるかな
時間のかかり具合であきらめる
(地味に編集) 2025/09/01(月) 23:35:13

回答ありがとうございます。

データの中身は、
X    Y    Z    R  G  B
100.123 90.335 90.123 56  20 30
120.334 90.532 89.885 20  55 38
 ・
 ・
 ・
というのが現状、約140万件あり

別に修正するデータのリストが約2000件
X    Y    Z    R  G  B
100.123 90.335 90.200 56  20 30
120.334 90.532 90.200 20  55 38

XとYの値が同じものを探してZの値を書き換えたいです。

年に数回しかこういう作業は行わないので、
使い捨てマクロで対応できればと思ってます。

ワードをあんまり使ったことないですが、ワードもありですね。
テキストエディターはちょっとこういう作業ができるかどうかがわからないですけど、
胴なんでしょう?
SQLite3は使い方を覚えるのに敷居が高く感じます

 >回答者の(まっつわん)さんですか。
そうです。最近は3DCAD的なソフトで遊んでいるので、
こちらはご無沙汰かと思います。

大量のデータを扱ったことがなく、
とっかかりのヒントがいただきたく質問してみました。
(まっつわん) 2025/09/02(火) 11:25:02


 >使い捨てマクロで対応できればと思ってます。
 とはいえ、速度的にはpython 使った方がいいと思います
 pandasというライブラリを使えば大きなファイルを分割して読みで処理できるはず

 最近はAIがさらっとコードを作成してくれますし
(´・ω・`) 2025/09/02(火) 12:15:26

 AIじゃないけど、こんな愚直なものではどうでしょう。

 Sub test()
     Const fname As String = "D:\MyDocuments\202509\testdata.csv"
     Dim dic As Object
     Dim textLine$
     Dim ary
     Dim k&, s$

     Set dic = CreateObject("Scripting.Dictionary")

     Open fname For Input As #1
     Do While Not EOF(1)
         Line Input #1, textLine
         ary = Split(textLine, ",")
         dic(ary(0) & "," & ary(1)) = ary(2)
     Loop
     Close #1

     For k = 1 To 10
         s = Cells(k, "A") & "," & Cells(k, "B")
         Cells(k, "D") = dic(s)
     Next
 End Sub

(xyz) 2025/09/02(火) 12:32:37


 200万件データでやりました。少し時間はかかるけど年に1,2回ならいいんじゃないかと。

(xyz) 2025/09/02(火) 12:34:40


 ざっくり1行40バイトとして、1000万行で400Mbyte 
 と考えたら、そんなに大きくないですね

 4Gbyte越えるとVBAでは読み込めないかもしれませんが、400MByteならいけるでしょう
(´・ω・`) 2025/09/02(火) 12:53:02

 VBAだと200秒かかりましたが、pythonだと0.8秒、julia は0.4秒でした。

(xyz) 2025/09/02(火) 13:54:51


 ファイルの関係が逆でした。
 2000件のデータを辞書に持ち、
 140万件のデータを
 1件読んで、
 ・辞書にあれば、修正したもので、別CSVに書き出し
  ・辞書になければ、そのまま      別CSVに書き出し
 これを繰り返します。
 コードは省略します。質問者さんに失礼にあたるかも。 

(xyz) 2025/09/02(火) 16:42:44


回答ありがとうございます。

pythonという言葉がよく出てきますが、新しい言語はちょっと時間がないかも。。。
AIもまだ余裕がないですね^^;

xyzさんのアドバイスにしたがって、
Openステートメント(?)を少し勉強してみました。

Option Explicit

Sub test()

    Const fOld As String = "床掘.csv"
    Const fNew As String = "床掘(2).csv"
    Const fList As String = "棄却点2.csv"
    Dim WSH As Object: Set WSH = CreateObject("WScript.Shell")
    Dim DT As String: DT = WSH.SpecialFolders("Desktop") & "\"
    Dim DIC As Object: Set DIC = CreateObject("Scripting.Dictionary")
    Dim s As String
    Dim ss As String
    Dim ary As Variant
    Dim i As Long, j As Long, k As Long
    Dim t

    t = Timer

    GetList DIC, DT & fList, i
    Debug.Print "i= " & i

    Open DT & fOld For Input As #1
    Open DT & fNew For Append As #2
    Do While Not EOF(1)
        j = j + 1
        Line Input #1, s
        ary = Split(s, ",")
        ss = ary(0) & "," & ary(1)
        If DIC.exists(ss) Then
            k = k + 1
            ary(2) = DIC(ss)
            Debug.Print "j= " & j
        End If
        Print #2, Join(ary, ",")
    Loop
    Close #1
    Close #2
    Debug.Print "k= " & k
    Debug.Print Timer - t
End Sub

Function GetList(ByRef oDic As Object, ByVal sFName As String, ByRef i As Long)

    Dim ary As Variant
    Dim txt As String

    Open sFName For Input As #1
    Do While Not EOF(1)
        Line Input #1, txt
        ary = Split(txt, ",")
        If IsNumeric(ary(1)) Then
            i = i + 1
            oDic(ary(1) & "," & ary(2)) = ary(3)
        End If
    Loop
    Close #1
End Function

コードを調べながら書いてデバッグして2時間。
辞書1000件に対して、データが5万件でテスト。
実行に0.5秒
データのチェックに10分(未実行だけど多分あってると思われ)

最近は、1クリックの操作で35秒待たされるようなソフトで遊んでいるので、
10分や20分待ってもぜんぜん平気かも^^;
これくらいなら、1年に1回〜2回なら十分かと思いました。
ロジック(?)は覚えたので、ファイルがどこかに埋もれてもなんとかなりそうです。(多分)

ありがとうございました。
(まっつわん) 2025/09/03(水) 15:55:13


 お疲れさまでした。
 コードも提示されましたので、同じような悩みを持つ方の参考になるものと思いました。

(xyz) 2025/09/03(水) 17:19:25


コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.