ディレクトリ構造を持つjsonファイルたちを形態素解析をしてcsvに一括変換

# 複雑なディレクトリ構造を持つjsonファイルをcsvに一括変換したい
日付毎に記録されたjsonデータをcsvに変換したいとする。
ここでまず以下の方法が考えられる
1. json⇒csvに変換してくれるサイトを利用
2. pythonの変換ライブラリ(pd.read_json()など)を使用する

しかしながら、このどちらも以下の問題を抱えていた
1...一度に変換できる容量に制限アリ&同様のディレクトリを手作業で作り直すのが面倒
2...pd.json_read()でエンコーディングエラー多発

そのため、今回はjson⇒numpy⇒csvとワンクッション置いて必要な情報のみを取り出した

# 1. 重for文をさけて2018-01-02.jsonのようなファイルパスを表現する
まずこのように内包表記を定義します

```python:
#内包表記で重複for分を避ける
    years = range(2018,2019)
    months = range(1, 13)
    days = range(1,32)

    combinations = [(year, month, day)
                    for year in years
                    for month in months
                    for day in days]
```
この内包表記を利用することで、for文は一度で表現することができます

```python:
    for year, month, day in combinations:
        #ファイル名に合うようにゼロ埋めを実行. ex)2018-09-01
        date = str(year) + '-' + str(month).zfill(2) + '-' + str(day).zfill(2)
        #pathの生成を自動化(ディレクトリ名もそのうち自動で)
        path = "C:/Users/名前/Desktop/json/目的のディレクトリ/" + str(date) + ".json"
```
# 2.ファイルパスの判定とjson⇒numpy
1でjsonファイルのpathを自動生成することが出来ました。しかしながら、生成した日付のjsonファイルがない場合エラーを吐いてしまいます。
そこで、os.path.isfile(path)という関数を使用することでpathの存在を判定し、同時にjson⇒numpyへ変換してしまいましょう


```python:
if(os.path.isfile(path)):
            #日付代わりにカウンターを更新。これが行の値になる
            count += 1
            #以下、encodingを指定しないとエラーを吐く
            f = None
            f = open(path, 'r', encoding="utf-8")
            #ファイルのデータを取得
            json_data = json.load(f)

            #numpyにぶち込む
            data_ = []
            data_ = np.array(json_data)
```
elseは今回特に指定しませんでした。

# 3.データのクリーニング(今回は自然言語処理用)と単語抽出
今回使用するjsonファイルの特徴を見てクリーニング方法を検討します
テキストを含むjsonファイルはすべて
{'type': 'message'
から始まっていたので、こちらを判定に利用しました


```python:
 #data_をクリーニングしてから全体の配列に格納
            for i in range(len(data_)):
                data_text = str(data_[i])
                text_ = data_text.split(',')
                #メッセージだけを取り出す
                if(text_[0]=="{'type': 'message'"):
                    rm = "'text': "
                    pure_text = clean_text(text_[2].replace(rm,''))
                    print(pure_text)
                    tokens = t.tokenize(pure_text)
                    for token in tokens:
                        partOfSpeech = token.part_of_speech.split(',')[0]
                        # 今回抽出するのは名詞だけ。（もちろん他の品詞を追加、変更、除外可能。）
                        if partOfSpeech == u'名詞':
                            each_data.append(token.surface) # token.surfaceは表層形(語彙)。詳しくはこちら...http://ailaby.com/janome/
                    #抽出した名詞たちをdata_allに追加していく。
                    data_all.append(each_data)
                    each_data = []
```

# 4. 形態要素解析後のデータをexcelファイルに出力
```python:
    ## 文章を形態素毎に分割したデータをいれるエクセルファイル作成（今回は名詞のみ）
    # 例）C:\Users\〜\Documents\〜
    # パスの前のrは省略しない
    data_book = xlsxwriter.Workbook("例）C:\Users\〜\Documents\ファイル名1.xlsx")
    # シート作成・変数定義
    data_sheet = data_book.add_worksheet('data')
    for row in range(len(data_all)):
        for i in range(len(data_all[row])):
            data_sheet.write(row, i, data_all[row][i])
    # エクセルを保存
    data_book.close()
```

# 5. 名詞の頻度ランキングをexcelファイルに出力
```python:
    #すべての語彙を同じ配列に格納
    chain_data = list(chain.from_iterable(data_all))
    c = Counter(chain_data)

    result_ranking = c.most_common(1000) # 出現頻度100位までを変数に格納
    # 語彙出現ランキングを記述するエクセルを作成（パスはファイルを作成したいところに）
    result_book = xlsxwriter.Workbook("例）C:\Users\〜\Documents\ファイル名2.xlsx")
    # resultという名前のシートを作成
    result_sheet = result_book.add_worksheet('result')
    for row in range(len(result_ranking)):
        for i in range(len(result_ranking[row])):
            result_sheet.write(row, i, result_ranking[row][i])
    # エクセルを保存
    result_book.close()
```

# 6.おつかれさまでした
これで大体のjsonファイルをcsvで取り扱えそうですね

#コード全文
```python:analysis.py
import pandas as pd
import json
import os
import os.path
import numpy as np
from janome.tokenizer import Tokenizer
import xlrd
import xlsxwriter
from collections import Counter
from itertools import chain

#テキストデータをクリーニングする関数
def clean_text(replaced_text):
    """
    \S+ matches all non-whitespace characters (the end of the url)
    :param html_text:
    :return:
    """
    replaced_text = re.sub(r'http\S+', '', replaced_text)
    replaced_text = re.sub(r'[@＠]\w+', '', replaced_text)  # メンションの除去
    replaced_text = re.sub(r'　', ' ', replaced_text)  # 全角空白の除去
    replaced_text = re.sub(r'<', ' ', replaced_text)  # 全角空白の除去
    replaced_text = re.sub(r'>', ' ', replaced_text)  # 全角空白の除去
    return replaced_text

########################################################
#メイン処理
if __name__ == "__main__":
    #内包表記で重複for分を避ける
    years = range(2018,2019)
    months = range(1, 13)
    days = range(1,32)

    combinations = [(year, month, day)
                    for year in years
                    for month in months
                    for day in days]

    #内包表記で繰り返し処理
    #縦軸の日付をうまく行列に反映できないので、とりあえずカウンターを設置する
    count = 0
    data_all = [] #テキストファイルのまとめ先
    each_data = [] #語彙の格納先
    t = Tokenizer() #形態素解析用のモジュール
    #1.形態素解析
    for year, month, day in combinations:
        #ファイル名に合うようにゼロ埋めを実行. ex)2018-09-01
        date = str(year) + '-' + str(month).zfill(2) + '-' + str(day).zfill(2)
        #pathの生成も自動化(channelもそのうち自動で)適宜読み替えてpathを設定してください
        path = "C:/Users/ユーザー名/Desktop/json/目標のディレクトリ/" + str(date) + ".json"
        if(os.path.isfile(path)):
            #日付代わりにカウンターを更新。これが行の値になる
            count += 1
            #encodingを指定しないとエラーを吐く
            f = None
            f = open(path, 'r', encoding="utf-8")
            #print(f)
            #ファイルのデータを取得
            json_data = json.load(f)
            #numpyにぶち込む
            
            data_ = []
            data_ = np.array(json_data)
            
            #count行目に入る値
            print(count)
            #data_をクリーニングしてから全体の配列に格納
            for i in range(len(data_)):
                #print(data_[i])
                data_text = str(data_[i])
                #print(data_text)
                text_ = data_text.split(',')
                #メッセージだけを取り出す
                if(text_[0]=="{'type': 'message'"):
                    rm = "'text': "
                    pure_text = clean_text(text_[2].replace(rm,''))
                    print(pure_text)
                    tokens = t.tokenize(pure_text)
                    for token in tokens:
                        partOfSpeech = token.part_of_speech.split(',')[0]
                        # 今回抽出するのは名詞だけ。（もちろん他の品詞を追加、変更、除外可能。）
                        if partOfSpeech == u'名詞':
                            each_data.append(token.surface) # token.surfaceは表層形(語彙)。詳しくはこちら...http://ailaby.com/janome/
                    #抽出した名詞たちをdata_allに追加していく。
                    data_all.append(each_data)
                    each_data = []

    ###########################################################
    ## 文章を形態素毎に分割したデータをいれるエクセルファイル作成（今回は名詞のみ）
    # 例）C:\Users\〜\Documents\〜
    # パスの前のrは省略しない
    data_book = xlsxwriter.Workbook("例）C:\Users\〜\Documents\ファイル名1.xlsx")
    # シート作成・変数定義
    data_sheet = data_book.add_worksheet('data')
    for row in range(len(data_all)):
        for i in range(len(data_all[row])):
            data_sheet.write(row, i, data_all[row][i])
    # エクセルを保存
    data_book.close()


    ############################################################
    #すべての語彙を同じ配列に格納
    chain_data = list(chain.from_iterable(data_all))
    c = Counter(chain_data)

    result_ranking = c.most_common(1000) # 出現頻度100位までを変数に格納
    # 語彙出現ランキングを記述するエクセルを作成（パスはファイルを作成したいところに）
    result_book = xlsxwriter.Workbook("例）C:\Users\〜\Documents\ファイル名2.xlsx")
    # resultという名前のシートを作成
    result_sheet = result_book.add_worksheet('result')
    for row in range(len(result_ranking)):
        for i in range(len(result_ranking[row])):
            result_sheet.write(row, i, result_ranking[row][i])
    # エクセルを保存
    result_book.close()
```