- ベストアンサー
エクセル 身長差と体重差から特定の人物を抽出
氏名、身長、体重を示した1万人のデータから、身長差が 15 cm、体重差 3.05 kg であるペアを特定し、抽出することはできるでしょうか。エクセル関数でできるのが理想ですが、他の方法(フリーソフト、マクロ、プログラミング)でもかまいません。教えていただけないでしょうか。よろしくお願いいたします。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
A1,B1,C1に氏名、身長、体重の項目、行2以下に1万個のデータがあるとする。条件に合った組をD2、E2以下に出力すれば、以下のコードになるでしょう。 総当たりだから時間がかかる。これで、15から20秒程度。 Sub test() Dim d, dl, dw n = 10000 d = Range("A2:C10001") k = 1 For i = 1 To n For j = i + 1 To n dl = Round(Abs(d(i, 2) - d(j, 2)), 2) dw = Round(Abs(d(i, 3) - d(j, 3)), 2) If dl = 15 And dw = 3.05 Then Cells(k + 1, 4) = d(i, 1) Cells(k + 1, 5) = d(j, 1) k = k + 1 End If Next Next End Sub
その他の回答 (5)
- okormazd
- ベストアンサー率50% (1224/2412)
#5です。 私は、元の質問に即した回答をしたのでこのQ/Aはこれで終わりです。後出しじゃんけんのように条件を変えたり、条件を追加したりなどにはきりがありませんので対応しません。もし、別の条件について教えてほしいのなら、新しく質問を立てましょう。 追加補足の内容は、私の回答が理解できれば、ごく簡単なことですから、自分で考えたらいかがですか。
お礼
ありがとうございました。 ご提案のとおりに、させていただきます。
- msMike
- ベストアンサー率20% (364/1805)
[No.1補足]へのコメント、 ある一人(氏名/身長/体重)に対して、身長差が±15cm、体重差が±3.05kg の人は当然のことながら複数(最多で千人以上?)存在するはずですが、Excel 上で「1万人のデータから」どういうレイアウト(姿)で抽出する(される)ことを考えていますか? まさか、「そんなこと考えてもいなかった」ではないことを祈っています。
お礼
ご回答ありがとうございました。 レイアウトを考えていませんでした。もう少し考えてからご質問いたします。
- imogasi
- ベストアンサー率27% (4737/17069)
1万人X1万人(正確には9999人?)の対を考えるのか? 実際はA-BとB-Aの比較対は同じであるから、半分程度になるのかな。ただし男女などがあって(他の回答者の疑問?)、身長の例で、男の方が高いケースだけを選ぶなら、また考えが多少違うと思う。 ーー このOKWAVEのこのカテの質問において、質問の意味を、十分{文章で}説明できてないと思うケースがほとんどで、嘆かわしい。質問の文章を読んだ人に、どういう疑問が出そうか想像できないようでは、、この処理を解決する資格はないのではないか。 (1)問題を深く考える習慣がない。すぐWEB質問コーナーへ質問している。 (2)実際のケースを他のケースに置き換えているが、その置き換え後のケースで、元に持っていた、データの性格が捨てられて見えなくなっている。 この質問では身長ー体重の例にしている。「ペア」といっているので、男女のペアを連想してしまう。この例えでわかりやすくなっている点、捨ててしまったもの、余分にイメージしてしまうものなど、よく考えるべきだ。 (3)問題の「大きさ」に気づくのも、勉強や経験が必要だがそれがない。 (4)エクセル関連の質問の場合として、エクセルの特徴を(何がむつかしいか)わかってないので、適切にポイントを絞れない。 などがあるように思う。 本質問のこの問題に限っては、数学的な素養のある人の多く見るコーナーに質問すべきような気がする。 ーー 1万人程度なら、今のエクセルやエクセルVBAで1億回のオーダーの比較処理はやったことがないので、スムーズに答えが出るかどうかな。 もう1桁少ないデータ数なら、VBAで2重ループで比較すれば、簡単な問題かな? For i=10000 For j=10000 (比較処理) Next j Next i ’--- 例示 Sub test01() '100件づつの比較 Columns(4).Clear '結果列クリア k = 1 '出力結果列第1行目を指す For i = 1 To 100 For j = 1 To 100 If i < j Then 'i-Jとj-iの比較は同じとして捨てる If Abs(Cells(i, "A") - Cells(j, "B")) > 40 Then '40以上の差がある対を出力 Cells(k, "D") = "'" & i & "-" & j '対のセルの行番号を出力 k = k + 1 '次は直下の行に出力準備 End If End If Next j Next i End Sub A,B列にそれぞれ100行について、100未満の乱数を発生し、そのデータを 使った。Rand関数はA列に100行出したらすぐに、元のセルに値のみ複写にして、固定化すること。そうでないと、新しくシートにデータを入れたりすると新しい乱数を取り直して、考えにくいから。 こちらにはデータがないので、乱数を使ったが、乱数の式は、A1セルに=INT(RAND()*90+10)のようなもの。以下行に99行複写。B列も同じ。 結果は乱数の性格上実行者によって違うので、載せても意味ないので、載せない。 1000件くらいなら「総当たり」法(上記)も処理時間的に心配は無いようだ。 ---- エクセルの関数で遣るとすると、 普通に考えると、関数の場合は結果を出すセルの列が1万列(エクセルの制約16000列)必要かな(注1)? それと結果が10000列に散らばると、見にくいので、まとめるためには、VBAなどの方が、やりやすい。 (注1)エクセル関数の達人が、ここに熟達した回答を挙げてくれればよいが。
お礼
ありがとうございました。
- Prome_Lin
- ベストアンサー率42% (201/470)
VBScriptで、プログラムを組みましたが、あまり実用的ではありません。 Option Explicit Dim a, b, c, d, i, j, k, v, w, x, y, z Set v = CreateObject("Scripting.FileSystemObject") Set w = v.GetFolder(".") Set x = CreateObject("Excel.Application") Set y = x.Workbooks.Open(w & "\Test_01.xlsx") Set z = y.Worksheets(1) k = 0 For i = 2 to 10000 For j = 3 to 10001 a = z.Cells(i, 2).Value b = z.Cells(j, 2).Value If a - b = 15 or b - a = 15 Then c = z.Cells(i, 3).Value d = z.Cells(j, 3).Value If c - d = 3 or d - c = 3 Then k = k + 1 z.Cells(k, 4).Value = i & "行目と" & j & "行目" End If End If Next Next y.SaveAs(w & "\Test_02.xlsx") y.Close x.Quit Set z = Nothing Set y = Nothing Set x = Nothing Set w = Nothing Set v = Nothing MsgBox("Finished!") これを、テキストエディかメモ帳に貼り付け、「~.vbs」という名前で保存します。 できれば、全角スペース2つをタブに一括置換しておいてください。 このプログラムをエクセルファイルのあるフォルダに放り込み、「Test_01.xlsx」(割と最初の方)のところを、実際のファイル名にします。 結果ファイル名「Test_02.xlsx」(下の方)も適当な名前を付けておきます。 「A」列が「氏名」、「B」列が「身長」、「C」列が「体重」という想定です。 そして、「1行目」は「項目行」になっている、すなわち「A1」に「氏名」、「B1」に「身長」、「C1」に「体重」という文言が入っていて、2行目以降に実際のデータが入っているという前提でのプログラムです。 実際に乱数を発生させて適当な「氏名」「身長」「体重」を1万人分作成して、実行してみると、なかなか終わらないので、100人分で試しました。 100人だと数秒なのですが、1,000人だと私のマシンで、10分ぐらいかかります。10,000人だと、恐ろしくて分かりません。 このプログラムでは、最初の1人目と2人目~最後までを順番に身長を比べていき、どちらかの差が「15」なら、そのふたりの「体重差」を調べ、どちらかの差が「3」なら、これで条件は満たしたので、そのふたりの「行」を「D」列に書き込む、という処理を行っています。 これを、延々とやっています。100人では、条件を満たす人は出て来ませんでしたが、1,000人だと、6組出て来ました(最初のペアを確認しましたが、間違いなく条件通りでした)。 体重差は「3.05」がご希望なので、このプログラムの「If c - d = 3 or d - c = 3 Then」のところ、2つの「3」を「3.05」にしてください。乱数を発生させるときに、100分の1まで作成するのが邪魔くさかったので、今回は10分の1までで試しました。 分からなければ、また、質問してください。 ただ、とにかく順番に恐ろしい回数調べますので、うんざりするぐらい時間がかかります。 きっと、もっと頭のいい人が、スマートなプログラムを組まれると思いますが、私ではこれが限界です。
お礼
ご回答ありがとうございました。 データサイズによりどうなるかですね。
- msMike
- ベストアンサー率20% (364/1805)
》 氏名、身長、体重を示した1万人のデータ… 》 …ペアを特定し… 此処でいう「ペア」の意味は? 単に二人一組? もし、男女一組の意味なら、性別データも必要?
補足
単に二人一組の意味です。差からの抽出のため、1対データ(AさんとBさんのように)になります。性別データは不要です。
お礼
ご回答ありがとうございました。 今後ともよろしくお願いいたします。
補足
ありがとうございました。コードの意味はよくわかっていないので、しらべます。 さらに追加でうかがいたいのですが、15 cm に範囲を持たせることは可能でしょうか。例えば 15.2 から15.5 cm など。