<jupyter_start><jupyter_text>**handson用資料としての注意点**普通、同じセル上で何度も試行錯誤するので、最終的に上手くいったセルしか残らず、失敗したセルは残りませんし、わざわざ残しません。今回はhandson用に 試行・思考過程を残したいと思い、エラーやミスが出ても下のセルに進んで処理を実行するようにしています。notebookのセル単位の実行ができるからこそのやり方かもしれません。良い。（下のセルから文は常体で書きます。）kunai (@jdgthjdg)---  ここまでの処理を整理して、2008〜2019のデータを繋いでみる  xls,xlsxファイルを漁る<jupyter_code>from pathlib import Path
base_dir = Path("../../../data")  # 相対パスが違うかも ../ の調整でいけるはず・・・
base_dir.exists()
list(base_dir.glob("*_kansai/*"))
p = list(base_dir.glob("*_kansai/*"))[0]
p.name
kansai_kafun_files = []
for p in base_dir.glob("*_kansai/*"):
    # AMeDASだけ弾く
    if not p.name.startswith("AMeDAS"):
        kansai_kafun_files.append(p)
kansai_kafun_files<jupyter_output><empty_output><jupyter_text>lock ファイルが混じってしまった。AMeDASだけ弾くと .lockファイルも入ってしまう（この時私がこのファイルをエクセル互換ソフトで開いていたため、.lockファイルが生成された）ので、試しに **読めない文字 ( ë╘ò▓âfü[â )** で引っ掛けてみる<jupyter_code>kansai_kafun_files = []
for p in base_dir.glob("*_kansai/*"):
    # AMeDASだけ弾くと .lockファイルも入ってしまうので、読めない謎の文字で引っ掛けてみる
    if p.name.startswith("ë╘ò▓âfü[â"):
        kansai_kafun_files.append(p)
kansai_kafun_files<jupyter_output><empty_output><jupyter_text>いけた(環境によっていけないみたいなので、その時は一つ上の、AMeDASを弾くパターンで) ソートしてもいいけど、どのみち日付データはとるのでこのまま ---  今までの処理を適用していく<jupyter_code>%matplotlib inline
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
#設定でDataFrameなどが長く表示されないようにします（画面領域の消費を抑えてhandsonをしやすくするため）
# 長い場合の途中の省略表示(...)を出す閾値の設定（折り返しとは無関係）
pd.set_option('max_rows',10)
pd.set_option('max_columns',20) # これを超えたら全部は表示しない。 A B C ... X Y Z のように途中を省く。
p = kansai_kafun_files[-1]
print(p)
df = pd.read_excel(p, skiprows=1).iloc[:,:-2]
df
str_concat_h0_23 = df["年"].astype(str)+"/"+df["月"].astype(str)+"/"+df["日"].astype(str)+"/"+(df["時"]-1).astype(str) # 時から1引いてる
df["date_hour"] = pd.to_datetime(str_concat_h0_23, format="%Y/%m/%d/%H")
df.set_index("date_hour", inplace=True)
df = df.drop(columns=["年","月","日","時",]) # こっちでも全然良い
df<jupyter_output><empty_output><jupyter_text>ここまでを関数にする 多くの試行錯誤があったがこれだけのコードに圧縮された・・・<jupyter_code>def load_kafun_excel(path):
    df = pd.read_excel(path, skiprows=1).iloc[:,:-2]
    str_concat_h0_23 = df["年"].astype(str)+"/"+df["月"].astype(str)+"/"+df["日"].astype(str)+"/"+(df["時"]-1).astype(str) # 時から1引いてる
    df["date_hour"] = pd.to_datetime(str_concat_h0_23, format="%Y/%m/%d/%H")
    df.set_index("date_hour", inplace=True)
    df = df.drop(columns=["年","月","日","時",]) # こっちでも全然良い
    return df
load_kafun_excel(p)<jupyter_output><empty_output><jupyter_text>for文で回す<jupyter_code>kansai_kafun_files
kafun_df_list = []
for p in kansai_kafun_files:
    df = load_kafun_excel(p)
    kafun_df_list.append(df)
kafun_df_list[0].shape<jupyter_output><empty_output><jupyter_text>リスト内のdfを行方向(縦方向, y方向)に連結する  **[pd.concat](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.concat.html)**df の連結/結合/マージ  http://pandas.pydata.org/pandas-docs/stable/user_guide/merging.html<jupyter_code>kafun = pd.concat(kafun_df_list, axis=1)
kafun.shape
kafun.columns<jupyter_output><empty_output><jupyter_text>ミスってcolumnsの数が成長した。横方向につながっている<jupyter_code>kafun = pd.concat(kafun_df_list, axis=0)  # Warning<jupyter_output>/opt/conda/lib/python3.7/site-packages/ipykernel_launcher.py:1: FutureWarning: Sorting because non-concatenation axis is not aligned. A future version
of pandas will change to not sort by default.

To accept the future behavior, pass 'sort=False'.

To retain the current behavior and silence the warning, pass 'sort=True'.

  """Entry point for launching an IPython kernel.<jupyter_text>warning された。 今後ソートしないとのこと<jupyter_code>kafun = pd.concat(kafun_df_list, axis=0, sort=False)
kafun.shape<jupyter_output><empty_output><jupyter_text>このaxis方向でも columns が倍くらいに増えている・・・<jupyter_code>kafun.columns<jupyter_output><empty_output><jupyter_text>恐らく年が変わった時に列の名前が変わったようだ（多分担当者も）   データのフォーマットが変わると、恐ろしく面倒なことが起きる・・・<jupyter_code>kafun_df_list[0].columns
kafun_df_list[1].columns<jupyter_output><empty_output><jupyter_text>想像以上に全然違う・・・ファイル名をみる<jupyter_code>kansai_kafun_files[0].name
kansai_kafun_files[1].name<jupyter_output><empty_output><jupyter_text>xlsとxlsxの頃から変わったのかも？　とりあえず ロードした時にcolumnsを表示する雑な関数を作って試す<jupyter_code>def show_columns(path):
    df = pd.read_excel(path, skiprows=1).iloc[:,:-2]
    return df.columns
for p in kansai_kafun_files:
    print(p, show_columns(p))<jupyter_output>../../../data/2010_kansai/ë╘ò▓âfü[â^2010(è╓É╝).xls Index(['年', '月', '日', '時', '彦根', '大津', '今津', '野洲', '京都', '舞鶴', '京北', '大阪',
       '豊中', '河内長野', '神戸', '西宮', '篠山', '山崎', '奈良', '吉野', '大和高田', '和歌山', '田辺',
       '中辺路'],
      dtype='object')
../../../data/2017_kansai/ë╘ò▓âfü[â^2017(è╓É╝).xlsx Index(['年', '月', '日', '時', '彦根市役所', '滋賀県琵琶湖・環境科学研究センター', '滋賀県高島合同庁舎',
       '滋賀県林業普及センター', '京都府立医科大学', '京都府中丹東保健所', '京都市右京区役所京北合同庁舎',
       '大阪合同庁舎第2号館別館', '豊中市役所第一庁舎', '泉大津市役所', '兵庫県立健康環境科学研究センター', '北山緑化植物園',
       '兵庫県篠山庁舎', '西播磨県民局西播磨総合庁舎', '奈良県産業振興総合センター', '奈良県吉野保健所', '橿原総合庁舎',
       '和歌山地方気象台', '和歌山県西牟婁振興局庁舎', '和歌山県東牟婁振興局'],
      dtype='object')
../../../data/2015_kansai/ë╘ò▓âfü[â^2015(è╓É╝).xlsx Index(['年', '月', '日', '時', '彦根市役所', '滋賀県琵琶湖・環境科学研究センター', '滋賀県高島合同庁舎',
       '滋賀県森林センター', '京都府立医科大学', '京都府中丹東保健所', '京都市右京区役所京北合同庁舎',
       '大阪府環境農林水産総合研究所', '豊中市役所第一庁舎', '泉大津市役所', '兵庫県立健康環境科学研究センター', '北山緑化植物園',
       '兵庫県篠山庁舎', '西播磨県民局西播磨総合庁舎', '奈良県産業振興総合センター', '奈良県吉野保健所', '橿原総合庁舎',
       '和歌山[...]<jupyter_text>年が順不同で見にくいので結局ソートしてみる<jupyter_code>sorted(kansai_kafun_files)<jupyter_output><empty_output><jupyter_text>---**もしソートがうまくいかないパスだったら sorted の key=を設定する**<jupyter_code>p.name[10:14]  # ファイル名から年を抜き出すスライスがこれだった
# フォルダ名にかかわらず、ファイル名の 20xx で数値のソートされる
sorted(kansai_kafun_files, key=lambda x:int(x.name[10:14]))
sorted(kansai_kafun_files, key=lambda x: (-1)*int(x.name[10:14]))  # マイナスにすれば逆になるのが分かる<jupyter_output><empty_output><jupyter_text>ソート後にまた columns を見る<jupyter_code>for p in sorted(kansai_kafun_files):
    print(p, show_columns(p))<jupyter_output>../../../data/2008_kansai/ë╘ò▓âfü[â^2008(è╓É╝).xls Index(['年', '月', '日', '時', '彦根', '大津', '今津', '野洲', '京都', '舞鶴', '京北', '大阪',
       '豊中', '河内長野', '神戸', '西宮', '篠山', '山崎', '奈良', '吉野', '大和高田', '和歌山', '田辺',
       '中辺路'],
      dtype='object')
../../../data/2009_kansai/ë╘ò▓âfü[â^2009(è╓É╝).xls Index(['年', '月', '日', '時', '彦根', '大津', '今津', '野洲', '京都', '舞鶴', '京北', '大阪',
       '豊中', '河内長野', '神戸', '西宮', '篠山', '山崎', '奈良', '吉野', '大和高田', '和歌山', '田辺',
       '中辺路'],
      dtype='object')
../../../data/2010_kansai/ë╘ò▓âfü[â^2010(è╓É╝).xls Index(['年', '月', '日', '時', '彦根', '大津', '今津', '野洲', '京都', '舞鶴', '京北', '大阪',
       '豊中', '河内長野', '神戸', '西宮', '篠山', '山崎', '奈良', '吉野', '大和高田', '和歌山', '田辺',
       '中辺路'],
      dtype='object')
../../../data/2011_kansai/ë╘ò▓âfü[â^2011(è╓É╝).xls Index(['年', '月', '日', '時', '彦根', '大津', '今津', '野洲', '京都', '舞鶴', '京北', '大阪',
       '豊中', '河内長野', '神戸', '西宮', '篠山', '山崎', '奈良', '吉野', '大和高田', '和歌山', '田辺',
       '中辺路'],
      dtype='object')
../../../data/2012_kansai/ë╘ò▓âfü[â^[...]<jupyter_text>---2015年にxlsxに変わった途端に・・・これでは元データのエクセルか、ウェブページの注釈的なものを探さないと追跡ができない  もういちどエクセルを見てみると、  古いデータには、 "地点" という別のシートがあった！ sheet_nameには文字列以外にもindexが使えるとdocumentに書いてあった。  誰かのブログをコピってるだけだったら気づけなかったかもしれない。（自戒）<jupyter_code>names = pd.read_excel("../../../data/2008_kansai/ë╘ò▓âfü[â^2008(è╓É╝).xls", sheet_name=1)
names<jupyter_output><empty_output><jupyter_text>列名をrenameするmapperを作るここからは適当にメソッドを探して対処していくしかない。。  pandas力が試される・・・mappingするなら辞書が良いから辞書っぽいのを探す<jupyter_code>names["地点名"].to_dict()<jupyter_output><empty_output><jupyter_text>key:value が index:列の値 となるdictができたので、index を "地点名" 列にして、"施設名" との .to_dictすれば良さそう<jupyter_code>rename_mapper = names.set_index("地点名")["施設名"].to_dict()
rename_mapper<jupyter_output><empty_output><jupyter_text>これ。きた。<jupyter_code>df.rename(columns=rename_mapper).head(1)
# OK<jupyter_output><empty_output><jupyter_text>関数に埋め込む<jupyter_code>def load_kafun_excel_renamed_columns(path):
    df = pd.read_excel(path, skiprows=1).iloc[:,:-2]
    try:
        name = pd.read_excel(path, sheet_name=1)
        rename_mapper = names.set_index("地点名")["施設名"].to_dict()
        df = df.rename(columns=rename_mapper)
        
    except Exception as e:
        print(path, e)
    
    str_concat_h0_23 = df["年"].astype(str)+"/"+df["月"].astype(str)+"/"+df["日"].astype(str)+"/"+(df["時"]-1).astype(str) # 時から1引いてる
    df["date_hour"] = pd.to_datetime(str_concat_h0_23, format="%Y/%m/%d/%H")
    df.set_index("date_hour", inplace=True)
    df = df.drop(columns=["年","月","日","時",]) # こっちでも全然良い
    return df
kafun_df_list = []
for p in sorted(kansai_kafun_files):
    df = load_kafun_excel_renamed_columns(p)
    kafun_df_list.append(df)
kafun_renamed = pd.concat(kafun_df_list, axis=0, sort=False)
kafun_renamed.shape<jupyter_output>../../../data/2015_kansai/ë╘ò▓âfü[â^2015(è╓É╝).xlsx list index out of range
../../../data/2016_kansai/ë╘ò▓âfü[â^2016(è╓É╝).xlsx list index out of range
../../../data/2017_kansai/ë╘ò▓âfü[â^2017(è╓É╝).xlsx list index out of range
../../../data/2018_kansai/ë╘ò▓âfü[â^2018(è╓É╝).xlsx list index out of range<jupyter_text>xlsxだけエラーになってくれてるのでxlsでは読み込めているようだ果たして結果は？<jupyter_code>kafun_renamed.columns<jupyter_output><empty_output><jupyter_text>---似た名前を探すためにソートしてみる<jupyter_code>kafun_renamed.columns.sort_values()<jupyter_output><empty_output><jupyter_text>---**'北山緑化植物園','北山緑化植物園（西宮市都市整備公社）'****'西播磨', '西播磨県民局西播磨総合庁舎'** とか同一では？  列名のゆらぎが・・・（予想はしていたがこれを全部追うのは大変なので今回はパス！） ここでHPをもう一度見てみると。  http://kafun.taiki.go.jp/library.html4>彦根地方気象台	彦根市城町２丁目５－２５	彦根	平成29年度に彦根市役所から移設  >舞鶴市西コミュニティセンター	舞鶴市字南田辺１番地	舞鶴	平成29年度に京都府中丹東保健所より移設  追っかけるのも大変、かつ、そこまでを求めていないため、今回は少ないデータも全部残して次へ進む --- （今回はしないが）もし少ないものを弾きたいなら全部の対応を探すのは流石に厳しそうなので、各列での NaNの値を数えてみて、NaNの値が少ないものは2008〜2018まで列名がつながっていると判断する **count()** がそれに当たる  **sort_values** でソートしている<jupyter_code>kafun_renamed.count().sort_values(ascending=True).head(10)
kafun_renamed.count().sort_values(ascending=False).head(10) # Falseにしなくても、上のコードをtailにするだけでも良い<jupyter_output><empty_output><jupyter_text>--- 一旦ここまでのデータをpickleに保存ここまでの処理で生成したDataFrameをpickleで保存しておく。  pickle にしておくと読み込みも一瞬。  最初からcsvなどを読んで成形して・・・を行うコードを書かなくても良いので、一時的なセーブデータとしては重宝する！（日付のパースなどの処理をやり直さなくて良いので高速）<jupyter_code>kafun_renamed
kafun_renamed.to_pickle("kafun03.pkl")<jupyter_output><empty_output><jupyter_text>現状のデータをplotしてみる<jupyter_code>kafun_renamed.京都府立医科大学.plot()
kafun_renamed.plot(legend=False)
kafun_renamed.tail()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.19151007691558758, 'fraction_numerical': 0.019959108168630123, 'mean_word_length': 6.895465026902383, 'pattern_counts': {'":': 0, '<': 97, '<?xml version=': 0, '>': 99, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '25', 'dir': 'jupyter-structured-clean-dedup', 'id': '4598', 'license': 'Apache-2.0', 'n_tokens_mistral': 6458, 'n_tokens_neox': 6499, 'n_words': 514, 'path': 'work/03_concat_df.ipynb', 'repo_name': 'hannari-python/pandas-handson', 'size': '10271'}