人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

<目的>関連したデータ同士をグループにまとめたい。
データベースの中の1つのデータを検索して、直接関係のあったデータを抽出してできたcsvファイルがあります。
現在、全てのデータに対してデータベース内検索して作った以下のような総当りデータがあります。
(No1のデータを検索したところ、No2,3,4のデータと関係があった。No2のデータを検索したところ、No1のデータと関係があった。・・・)
↓csvファイル------------
1,2,3,4
2,1
3,1,4
4,1,3,5
5,4
6,7
7,6
8
↑csvファイル-----------

ここで、直接的および間接的に関係のあるもの同士を1つのグループにまとめたいと考えています。
上の例では以下のような3つのグループにまとめられます。

1,2,3,4,5
6,7
8

このようにグループにまとめる処理をどのようにおこなったらよいでしょうか?
当方はPerlとExcelマクロであれば多少わかります。
ただし処理したい実際のcsvファイルは12万行あるのでExcelには収まりませんでした。
出来ればPerlのコードを書いていただけると非常に助かります。
よろしくお願いします。

●質問者: cacataga
●カテゴリ:コンピュータ
✍キーワード:CSV Excel NO2 Perl グループ
○ 状態 :終了
└ 回答数 : 2/2件

▽最新の回答へ

1 ● jccrh1
●200ポイント ベストアンサー

EXCEL VBAで作成しました。

関係したNOは番号が数字か分かりませんでしたので、連想配列で判別をしました。

→参照設定で「Microsoft Scripting Runtime」を追加してください。

CSV入出力ファイルのフォルダはEXCELファイルと同一フォルダーで処理するようにしました。

ファイル名は変更してください。

Option Explicit
Sub 集計処理()
 Const CSV_IN = "\関連データ.csv"
 Const CSV_OT = "\グループデータ.csv"
 Dim グループ判定 As New Scripting.Dictionary
 Dim 判定番号 As Long
 Dim 決定番号 As Long
 Dim グループCSV(120000) As String
 Dim 関連データ As String
 Dim 分解 As Variant
 Dim I As Long

 Open ThisWorkbook.Path & CSV_IN For Input As #1
 Do While Not (EOF(1))
 Line Input #1, 関連データ
 分解 = Split(関連データ, ",")
 If グループ判定.Exists(分解(0)) Then ' グループにある場合
 決定番号 = グループ判定.item(分解(0))
 グループCSV(決定番号) = グループCSV(決定番号) & "," & 分解(0)
 Else ' グループにない場合
 判定番号 = 判定番号 + 1
   決定番号 = 判定番号
   グループ判定.Add (分解(0)), 決定番号
   グループCSV(決定番号) = 分解(0)
 End If
 For I = 1 To UBound(分解)
 If Not (グループ判定.Exists(分解(I))) Then
 グループ判定.Add (分解(I)), 決定番号
 End If
 Next I
 Loop
 Close
 
 Open ThisWorkbook.Path & CSV_OT For Output As #1
 For I = 1 To 判定番号
 Print #1, グループCSV(I)
 Next I
 Close
End Sub
◎質問者からの返答

回答ありがとうございました!

回答をあけるのが遅くなってしまい申し訳ありませんでした。

さきほど数個のデータについて試してみたところ、うまく処理されていました。

VBAに関してはまだ勉強不足で書いてくださったコードの詳細についてはわからないところもありますが、これを良い教科書に勉強したいと思います。


2 ● airplant
●200ポイント

興味を惹かれたので、ExcelのVBAでテキストを読み込んでグループ化するマクロを作ってみました。シートにはデータを読み込んでいませんので、行数は12万行でも大丈夫です。試しに1万行を数字や英文でやってみましたが、数秒で終わるので12万行でもすぐに終わるものと思います。


Option Explicit

Sub GetRelationGroup()
 
 Const sInFile = "C:\temp\in.csv"
 Const sOutFile = "C:\temp\ans.csv"
 Dim sTextLine As String
 Dim sSplitBuf() As String
 Dim i As Long, j As Integer, lCnt As Long
 Dim bFind As Boolean
 Dim sNewKeys As String
 Dim vGroup() As Variant
 Dim sGroupWrk() As String
 
 Open sInFile For Input As #1
 lCnt = -1
 Do While Not EOF(1)
 Line Input #1, sTextLine
 sSplitBuf = Split(sTextLine, ",")
  '後ろのNull値は無効にする 1,2,,,,,→1,2
 For j = 0 To UBound(sSplitBuf)
 If sSplitBuf(j) = "" Then
 If j = 0 Then GoTo Continue
 ReDim Preserve sSplitBuf(j - 1) As String
 Exit For
 End If
 Next
 bFind = False
 For i = 0 To lCnt
 sNewKeys = ""
 For j = 0 To UBound(sSplitBuf)
 sGroupWrk = vGroup(i)
 If FindStr(sGroupWrk, sSplitBuf(j)) Then
 bFind = True
 Else
  'keyなし:追加する
 sNewKeys = sNewKeys & "," & sSplitBuf(j)
 End If
 Next
 If bFind Then
  '関係分を追加
 vGroup(i) = Split(Join(vGroup(i), ",") & sNewKeys, ",")
 Exit For
 End If
 Next
 
 If Not bFind Then
 lCnt = lCnt + 1
 ReDim Preserve vGroup(lCnt) As Variant
 vGroup(lCnt) = sSplitBuf
 End If
Continue:
 Loop
 Close #1
 Open sOutFile For Output As #2
 For i = 0 To lCnt
 Print #2, Join(vGroup(i), ",")
 Next
 Close #2
 
End Sub


'Filter関数のマッチ版
Function FindStr(sSrcArray() As String, sFindStr As String) As Boolean

 Dim m As Integer
 
 FindStr = False
 For m = 0 To UBound(sSrcArray)
 If sSrcArray(m) = sFindStr Then
 FindStr = True
 Exit Function
 End If
 Next

End Function
◎質問者からの返答

回答ありがとうございました!

回答をあけるのが遅くなってしまい申し訳ありませんでした。

わかりやすく色付けしたコードで書いてくださり、ご配慮に感謝です。

さきほど試しまして問題なく処理されているのを見て、VBA初心者の私から見たらただ敬服する次第です。

興味を持っていただいたようで参考までにお知らせしますが、処理するデータは遺伝子の塩基配列のデータから直接関係のある遺伝子同士を結びつけ、書いてくださったコードによって間接的に関連のある遺伝子をグループにまとめたということをしたかったのです。

おかげさまで解析を終えることが出来ました。

どうもありがとうございました!

関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ