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

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

ただいまの
回答率

89.54%

1次元ではないデータ同士の相関を知る方法

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 126

dendenmushi

score 62

前提・実現したいこと

あるアンケートの選択肢3つ(A,B,C)のうち、どれを選んだか、回答者の性別と年齢、その他のデータ、結果何を選んだのかデータがあらかじめあるとき、新しい人が何を選択するのか予想したい。

ID 性別 年齢 ・・・ ・・・ ・・・ 選択した肢
1 1 31 Aを選択
1 2 46 Cを選択
455 1 32 ?

試したアプローチ方法

人物のデータの1行ごとに特徴量を出して、新しい人と最も相関している人物の結果を参考にする方法。
つまり、すべての要素をone-hotで表してから、ベクトル(1次元変換)にしてからベクトル相関を求める方法になります。

import numpy as np
results = np.corrcoef(arr6)
print("相関係数を出力")
print(results)

発生している問題・エラーメッセージ

arr4 = [[1.], [1.], [0.], [1.]]
arr3 = [[1.], [1.], [0.], [0.]]


これらの2次元配列ですと1次元ベクトルではないためエラーになります。
これらの相関係数を知るにはどうしたらよいのでしょうか。

arr4 = [[1.], 1., [0.], [1.,0.]]
arr3 = [[1.], 1., [0.], [0.,1.]]


また、このようなときに1次元の要素,2次元の要素がある場合の2つのデータの相関を知りたい場合はどのようにすればよいのでしょうか。

試した方法

これらを1次元のベクトルに変換も考えましたが、reshape(-1,)でも変換できませんでした。
そもそも2次元要素をもっていたためです。

他アプローチ

one-hotに拘らず、性別男は1、女は2、趣味が手芸なら1、ボクシングなら2…読書なら72などのように数値に変換してしまえば、1次元のベクトルになるとも考えました。これでベクトルを作り、あとはcorrcoefで比較し出す相関係数は結果参考にするには正しい考え方でしょうか。アドバイスどなたか頂けないでしょうか。よろしくお願い致します。

補足

win10
python3.7

2020/03/21追記(8:11訂正)

ごめんなさい間違えました。1次元には変換はできてもリスト型になってしまって、その後の相関係数を求める際に、リストが入っているのでだめですよと言われてしまうエラーでした。

import numpy as np
d_float_y = np.array([
                      [0.],1.,0.
                      ])
e_float_y = np.array([
                      [1.],1.,0.
                      ])
print(d_float_y.flatten())   # 1次元に3つあるものを1次元K個にreshapeできる
print(e_float_y.flatten())
arr6 = []
import numpy as np
arr6.append(d_float_y)
arr6.append(e_float_y)
print(arr6)
results = np.corrcoef(arr6)
print("相関係数を出力")
print(results)


↓結果

[list([0.0]) 1.0 0.0]
[list([1.0]) 1.0 0.0]
[array([list([0.0]), 1.0, 0.0], dtype=object), array([list([1.0]), 1.0, 0.0], dtype=object)]
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-14-97f2f6639cde> in <module>()
     13 arr6.append(e_float_y)
     14 print(arr6)
---> 15 results = np.corrcoef(arr6)
     16 print("相関係数を出力")
     17 print(results)

<__array_function__ internals> in corrcoef(*args, **kwargs)

3 frames
<__array_function__ internals> in cov(*args, **kwargs)

<__array_function__ internals> in average(*args, **kwargs)

/usr/local/lib/python3.6/dist-packages/numpy/core/_methods.py in _mean(a, axis, dtype, out, keepdims)
    149             is_float16_result = True
    150 
--> 151     ret = umr_sum(arr, axis, dtype, out, keepdims)
    152     if isinstance(ret, mu.ndarray):
    153         ret = um.true_divide(

TypeError: can only concatenate list (not "float") to list
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+1

one-hotに変換する部分のコードがありませんが、失敗している気がします。

そもそも本当にカテゴリ数が合っているのかも疑問ですが、[[1.], 1., [0.], [1.,0.]]なら[1., 1., 0., 1.,0.]のような配列を得るべきです。また、年齢のようなnumericalな特徴量があるなら、それはそのまま入れるしかないでしょう。

数値とダミー変数が混ざると、単純な相関ではかなり厳しくなるので、機械学習をおすすめします。

実際に前処理をどうやるべきか? ですが、scikit-learnで書くとこんな感じです。

6.1. Pipelines and composite estimators — scikit-learn 0.22.2 documentation
scikit-learnのColumnTransformerを使ってみる - 静かなる名辞(拙記事)

自分で書いても良いのですが、one-hot変換をちゃんと実装するのはけっこう面倒くさいです。特段の理由がなければscikit-learnを(あるいは他の機械学習ライブラリを)勧めます。


one-hotに拘らず、性別男は1、女は2、趣味が手芸なら1、ボクシングなら2…読書なら72などのように数値に変換してしまえば、1次元のベクトルになるとも考えました。これでベクトルを作り、あとはcorrcoefで比較し出す相関係数は結果参考にするには正しい考え方でしょうか。

名義尺度の数値になりますので、うまくいきません。たとえば、「趣味:手芸」は「趣味:読書」より「趣味:ボクシング」に近いと考えることは無意味ですが、数値にエンコードして距離とか相関を測ると、そういうことをやるのと同じ結果になります。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/03/21 08:47 編集

    d_float_y = np.array([
    [0.],1.,0.
    ])
    これは要素がただの数値とone-hotのような2次元データが混ざってしまっているものを想定したテスト作成データでした。失礼しました。実際は以下のようになるとその際は考えていました。
    性別
    →男:[0,1]
    →女:[1,0]
    年齢:31歳
    趣味:手芸:1,ボクシング:2,読書:3
    data = np.array([
    [0.,1],31.,3.
    ])
    でもまだ、サイト読み込み終わっていないですが、これらをベクトルのように特徴を出して、他のIDの特徴と相関していく考えは難しい(無理?難易度が高い?)ということなんでしょうかね。今日はこちら精読したいと思っております。

    追記すみません。
    本当にこれを実現するのであれば、全てを同じ要素数に合わせる
    data = np.array([
    [0.,1…90個分まで0.を追加],[0.,0.,…31個目を1,0.,…90歳分まで0追加].,[0.,0.,3.,0…90個分まで0を追加]
    ])

    キャンセル

  • 2020/03/21 08:52 編集

    性別:男, 性別:女, 年齢, 趣味:手芸, 趣味:ボクシング, 趣味:読書
    [0, 1, 31, 0, 0, 1]
    という感じで作れば、とりあえずnumpy配列にしてデータ分析とかに回すことができます。
    ネストした構造にはしないです。
    (なお、基本的には複数の行(個体)のデータをまとめて単一の配列に入れるので、データは2次元です。(サンプル数, 特徴量の次元数)のshapeになります)

    キャンセル

  • 2020/03/21 08:58 編集

    ネストはしないのですね…1次元として数値データとして分析することについてわかりました。ありがとうございます。
    >性別:男, 性別:女, 年齢, 趣味:手芸, 趣味:ボクシング, 趣味:読書
    >[0, 1, 31, 0, 0, 1]
    これはやり方としても簡単でわかりやすいですね。データじたいは2次元。あくまでひとつのIDがひとつの多次元ベクトルになり、そのベクトル同士を相関させていくということですね。ありがとうございます。

    キャンセル

+1

ndarrayが2次元であることが問題で,1次元に変換したいのでしたら,flatten関数を使うことで,1次元の配列に変換できます.

追記

import numpy as np
arr6 = []
arr4 = np.ravel([[1.], [1.], [0.], [1.]])
arr3 = np.ravel([[1.], [1.], [0.], [0.]])
print(arr4)
print(arr3)
results = np.corrcoef(arr4, arr3)
print(results)


で実行できますがこれでやりたいことが実現できているでしょうか?
実行結果は

[1. 1. 0. 1.]
[1. 1. 0. 0.]
[[1.         0.57735027]
 [0.57735027 1.        ]]

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/03/21 07:47

    回答ありがとうございます。flattenとreshape(-1,)はほぼ同じで<元を変化させるかだけ>試したのですが、[]の中に、さらに[]があるとエラーになってしまいました。補足情報を本文に追加します。

    キャンセル

  • 2020/03/21 08:22 編集

    こんな方法があるのですね。勉強になりました。ありがとうございます。例えば、
    arr4 = np.ravel([[1.], [1.], [0.,1.], [1.]])
    arr3 = np.ravel([[1.], [1.], [0.,1.], [0.]])
    のようなリストの要素が変わるものがあるときは、エラーがでるようです。
    TypeError: unsupported operand type(s) for /: 'list' and 'int'
    このときは、すべての要素の数をあえて合わせた方がいいということですね。
    例えば以下のように
    arr4 = np.ravel([[1.,0.], [1.,0.], [0.,1.], [1.,0.]])
    arr3 = np.ravel([[1.,0.], [1.,0.], [0.,1.], [0.,0.]])
    強引に合わせてしまえば比較はできると考えていますがもし認識おかしければ教えて頂けないでしょうか。

    キャンセル

  • 2020/03/21 11:18

    どちらも非常に参考になりました。ありがとうございました。またよろしくお願い致します。

    キャンセル

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

  • ただいまの回答率 89.54%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる