91689


### 解決したいこと

シミュレーションデータの元データからある条件以上を抽出し←「こちらは完了している」

そのデータをクラスタリングして訪問先の抽出を行おうとしているのですがここでエラーが起きてしまいました

### 実行環境

・Excelに元データがある  
・コマンドプロンプトでpythonを開く  
・メモ帳にプログラミングを書きhoge.pyで保存  
・コマンドプロンプトで実行

### 発生している問題・エラー

[code]

    C:\datasyori>python hoge.py
        latitude   longitude
    0  35.693590  139.712202
    1  35.693497  139.712096
    2  35.693217  139.712261
    3  35.693549  139.712430
    4  35.693621  139.712501
    Traceback (most recent call last):
      File "C:\Users\mable\AppData\Local\Programs\Python\Python310\lib\site-packages\pandas\core\indexing.py", line 769, in _validate_tuple_indexer
        self._validate_key(k, i)
      File "C:\Users\mable\AppData\Local\Programs\Python\Python310\lib\site-packages\pandas\core\indexing.py", line 1378, in _validate_key
        raise ValueError(f"Can only index by location with a [{self._valid_types}]")
    ValueError: Can only index by location with a [integer, integer slice (START point is INCLUDED, END point is EXCLUDED), listlike of integers, boolean array]
    
    The above exception was the direct cause of the following exception:
    
    Traceback (most recent call last):
      File "C:\datasyori\hoge.py", line 95, in <module>
        Cn = C.iloc[Tn,0]
      File "C:\Users\mable\AppData\Local\Programs\Python\Python310\lib\site-packages\pandas\core\indexing.py", line 961, in __getitem__
        return self._getitem_tuple(key)
      File "C:\Users\mable\AppData\Local\Programs\Python\Python310\lib\site-packages\pandas\core\indexing.py", line 1458, in _getitem_tuple
        tup = self._validate_tuple_indexer(tup)
      File "C:\Users\mable\AppData\Local\Programs\Python\Python310\lib\site-packages\pandas\core\indexing.py", line 771, in _validate_tuple_indexer
        raise ValueError(
    ValueError: Location based indexing can only have [integer, integer slice (START point is INCLUDED, END point is EXCLUDED), listlike of integers, boolean array] types
    
[/code]

### 該当するソースコード

[code]

    #訪問先の抽出
    
    from matplotlib import pyplot as plt
    from sklearn import datasets, preprocessing
    from sklearn.cluster import KMeans
    import numpy as np
    import pandas as pd
    import cartopy.crs as ccrs
    import cartopy.io.shapereader as shpreader
    
    pd.set_option('display.max_rows',600)
    #前処理後のcsvを読み込み
    yomi=pd.read_csv("simulationkai.csv")
    df=pd.read_csv("simulationkai.csv",usecols=["longitude","latitude"])
    
    # DataFrameに変換
    print(df.head())
    # データの整形
    X = df
    
     
    # クラスタリング
    cls = KMeans(n_clusters=4)
    
    result = cls.fit(X)
    X['cluster'] = result.labels_
    PC= pd.DataFrame(X['cluster'])
    PC
    df.head()
    #yomiのデータフレームにcluster(クラスタ番号)を追加する
    yomi['cluster_id']=PC
    yomi
    
    #yomi(元データにクラスタ番号を追加したもの)をallclsdata.csvに保存する
    yomi.to_csv("allclsdata.csv")
    
    D = X.sort_values(by="cluster")
    D = D.drop_duplicates(subset='cluster')
    D
    # 各クラスタ内のデータ数をカウント
    V = X['cluster'].value_counts()
    V
    # 各クラスタの番号とデータ数をclsvalue.csvに保存
    V.to_csv("clsvalue.csv")
    
    
    # クラスタの重心確認
    C = pd.DataFrame(result.cluster_centers_)
    C
    
    C.iloc[0, :]
    
    
    lat= X['latitude'].tolist()
    lon= X['longitude'].tolist()
    
    clat=C[0].tolist()
    clon=C[1].tolist()
    
    
    #から1800までのクラスタのデータからそれぞれ同じ被験者の重複を省いてデータ人数を取得して順番にCSVにまとめる
    from csv import writer
    #pp = pd.DataFrame
    #ppi =  pd.DataFrame
    #yomiからWhile文でN番目のクラスタのデータのみ抽出
    i = 0
    while i <= 3:
      yomic = yomi[yomi['cluster_id']== i]
    #N番目のクラスタdfから被験者idの重複を消す
      yomics = yomic.drop_duplicates(subset=["id_questionnaire"])
    #N番目の加工後データの行数をCSVに付け足す
      #file = [i,len(yomics)]
      #ppi = pp.append([file], ignore_index=True)
      #ppi.to_csv("pp.csv")
      list_data=[i,len(yomics)]
      with open('pp.csv', 'a', newline='') as f_object:  
       writer_object = writer(f_object)
       writer_object.writerow(list_data)  
       f_object.close()
      i = i + 1
    #else:
      #ppi.to_csv("pp.csv") 
    
    #pp.csv内の人数を降順にしたものをpps.csvに保存
    PP = pd.read_csv("pp.csv",names=["cls","people"])
    T = PP.sort_values(by=["people"],ascending=False)
    T.to_csv("pps.csv")
    PP.to_csv("pp.csv")
    
    #pps.csvの上から順番にクラスタ番号を引き出してその番号の座標をCから引き出す
    num = 0
    while num <= 3:
      Tn = T.iloc[num,0]
      #Tno = Tn + 1
      Cn = C.iloc[Tn,0]
      Cn2 = C.iloc[Tn,1]
      list_data2=[Tn,Cn,Cn2]
      with open('point.csv', 'a', newline='') as f_object:  
       writer_object = writer(f_object)
       writer_object.writerow(list_data2)  
       f_object.close()
      num = num + 1  
    
    dfh = pd.read_csv("point.csv",names=["cluster_id","latitude","longitude"])
    B = pd.read_csv("pps.csv",usecols=["people"])
    #dfh2= pd.DataFrame(B['people'])
    dfh['people']= B
    dfh.to_csv("point.csv")
    
[/code]

### 自分で試したこと

Cnの値に対しての型がエラーが起きているようなのですが勉強不足でよく理解できていないです

### 補足情報

Python 3.10.4 (tags/v3.10.4:9d38120, Mar 23 2022, 23:13:41) [MSC v.1929 64 bit
(AMD64)] on win32


CC BY-SA 4.0
2022-10-19T09:45:42.343
91679
2022-10-20T07:23:42.987
2022-10-20T00:22:56.740
3060
54916
question
python
pythonでK-meansクラスタリングしたいがエラーが出る: ValueError: Can only index by location with a [integer, ...]


まず，エラー情報ですが 95行目の

[code]

    Cn = C.iloc[Tn,0]
    
[/code]

で発生し，内容は「位置情報ベースのインデキシング（ .iloc[]
）は『整数，整数スライス，整数リスト，ブール型配列』のみ受け（入れ）ることができる」です。  
そこで， 95行目の直前に

[code]

    print(num, Tn, type(Tn))
    
[/code]

を挿入して，適当に入力データ（simulationkai.csv）を作って実行してみたところ，以下のことがわかりました。  
・1回目の実行ではエラーは発生せず， Tnは整数値（1, 0, 2, 3）  
・2回目以降の実行ではエラーが発生し， Tnは str型（文字列）の 'cls'  
このことから，恐らく1回目に実行した際に作られた csvファイルが影響していると考え， Tn -> T -> PP -> pp.csv と遡って 76行目の

[code]

    with open('pp.csv', 'a', newline='') as f_object:
    
[/code]

に辿り着きました。そして，この行が whileループの初回（i = 0）でも実行されているために，過去に作られた pp.csv
に追記（'a'）しているようです。そこで，下記のように whileループの初回のみ上書き（'w'）になるように変更したところエラーは発生しなくなりました。

[code]

    with open('pp.csv', 'w' if i == 0 else 'a', newline='') as f_object:
    
[/code]


CC BY-SA 4.0
2022-10-20T06:48:18.423
91689
2022-10-20T07:23:42.987
2022-10-20T07:23:42.987
54588
54588
91679
answer