

【はじめに】  
pythonでタプルを用いた辞書の作成を試みているのですが、エラーが起こり、作成できません。  
恐れ入りますが、エラーの改善方法をご教授下さりますと幸いに存じます。  
何卒よろしくお願い申し上げます。

【実現したいこと】  
現在、グラフ理論を勉強しており、その過程で以下のような辞書を作成しております。

[code]

    dicts = {(i_1,j_1):length_1, (i_2,j_2):length_2,..., (i_10,j_10):length_10}
    
    i:出発するnode
    j:到着するnode
    length:iとjの間の距離
    
[/code]

具体的には、添付しておりますtest.csvの数値を代入し、以下のような辞書を作成を目指しております。

[code]

    dicts = {(2,20):100, (4,18):200,..., (20,2):1000}
    
[/code]

【試したこと・発生している問題(エラーメッセージ)】  
該当のソースコードを実行しますと、以下のようなエラーを出力します。  
エラーをネットで調べてみたのですが理解できませんでした。  
numpyに問題があるようですがどうしてもnumpyを使用したく、他のデータを読み込む方法(pandas等)は試しておりません。

[code]

    TypeError: unhashable type: 'numpy.ndarray'
    
[/code]

【該当のソースコード】  
辞書の作成を目指し、以下のようなプログラムを組みました。

[code]

    import numpy as np
    
    data = np.loadtxt("test.csv",      
                      delimiter=",",   
                      skiprows=1,      
                      usecols=(1,2,3) 
                     )
    
    keys = [(data[i:i+1,0:1],data[i:i+1,1:2]) for i in range(0,10)]
    values = [data[i:i+1,2:3] for i in range(0,10)]
    
    dicts={}
    for i in keys:
        for x in values:
           dicts[i] = x
           print(dicts)
    
[/code]

test.csvは以下の通りです。

[code]

    fid i   j   length
    1   2   20  100
    2   4   18  200
    3   6   16  300
    4   8   14  400
    5   10  12  500
    6   12  10  600
    7   14  8   700
    8   16  6   800
    9   18  4   900
    10  20  2   1000
    
[/code]


CC BY-SA 4.0
2021-09-03T10:32:35.420
82213
2021-09-19T13:41:56.077
47353
question
python numpy csv
numpyでcsvファイルを読み込み、(csvファイルのデータが入った)タプルを用いた辞書を作成したい


[teratail にて lehshell 様に回答いただきました](https://teratail.com/questions/357618)
ので以下に共有させていただきます。  
改めまして、ご協力下さりました皆様に感謝申し上げます。

* * *
[code]

    TypeError: unhashable type: 'numpy.ndarray'
    
[/code]

numpy.ndarray は unhashable なので辞書のキーにはできないということです。  
（hashable なものしか辞書のキーにはできません）

このようにすればいいでしょう。  
`range(0,10)` を `range(len(data))` に修正しました。

[code]

    import numpy as np
    
    data = np.loadtxt("test.csv",      
                      delimiter=",",   
                      skiprows=1,      
                      usecols=(1,2,3) 
                     )
    
    # keys = [(int(data[i:i+1,0:1]), int(data[i:i+1,1:2])) for i in range(0,10)]
    # values = [int(data[i:i+1,2:3]) for i in range(0,10)]
    keys = [(int(data[i:i+1,0:1]), int(data[i:i+1,1:2])) for i in range(len(data))]  # 10 削除
    values = [int(data[i:i+1,2:3]) for i in range(len(data))]  # 10 削除
    dic = {n:values[i]  for i,n in enumerate(keys)}
    print(dic)  # {(2, 20): 100, (4, 18): 200, ...}
    
[/code]


CC BY-SA 4.0
2021-09-19T08:41:39.453
82579
2021-09-19T11:10:23.283
2021-09-19T11:10:23.283
3060
47353
82213
answer


このようにもできます

[code]

    dct = dict(zip(map(tuple, data[:, :2]), data[:, 2]))
    display(dct)
    
[/code]

分解するとこんな感じ (コメントにより修正: `1:3` => `:2`, `3` => `2`)

[code]

    k = data[:, :2]   # keys: numpy.ndarray
    v = data[:, 2]     # values: array like
    k_t = map(tuple, k)
    dict(zip(k_t, v))
    
[/code]


CC BY-SA 4.0
2021-09-19T11:48:34.107
82580
2021-09-19T12:14:42.333
2021-09-19T12:14:42.333
43025
43025
82213
answer


[numpy.loadtxt — NumPy v1.21
Manual](https://numpy.org/doc/stable/reference/generated/numpy.loadtxt.html)
には `unpack` という keyword が用意されています。

> **unpack** : bool, optional
>
> If True, the returned array is transposed, so that arguments may be unpacked
> using x, y, z = loadtxt(...). When used with a structured data-type,
> **arrays are returned for each field**. Default is False.

この機能を使って以下の様にも書くこともできます。

[code]

    import numpy as np
    
    i, j, length = np.loadtxt(
      'test.csv', delimiter=',', skiprows=1,
      usecols=(1, 2, 3), dtype=int, unpack=True)
    
    dic = dict(zip(zip(i, j), length))
    print(dic)
    
    #=>
    {(2, 20): 100, (4, 18): 200, (6, 16): 300, (8, 14): 400, (10, 12): 500, (12, 10): 600, (14, 8): 700, (16, 6): 800, (18, 4): 900, (20, 2): 1000}
    
[/code]

~~> numpyに問題があるようですがどうしてもnumpyを使用したく、他のデータを読み込む方法(pandas等)は試しておりません。

とのことですが、pandas を使うと簡単に変換できるので参考までに紹介しておきます。

[code]

    import pandas as pd
    from pprint import pprint
    
    df = pd.read_csv('test.csv')
    dfx = df.set_index(['i', 'j'])['length'].to_dict()
    
    pprint(dfx)
    
    # =>
    {(2, 20): 100,
     (4, 18): 200,
     (6, 16): 300,
     (8, 14): 400,
     (10, 12): 500,
     (12, 10): 600,
     (14, 8): 700,
     (16, 6): 800,
     (18, 4): 900,
     (20, 2): 1000}
    
[/code]

~~


CC BY-SA 4.0
2021-09-19T12:24:28.453
82582
2021-09-19T13:41:56.077
2021-09-19T13:41:56.077
47127
47127
82213
answer