☆☆ 新着記事 ☆☆

2018年10月15日月曜日

Python 3でCSVファイルの操作

Python3で、CSVファイルの操作する時のポイントをまとめています。

(発展:)Python CSVを扱う時のリストと辞書を研究する

1.読み込み

csvモジュールをインポートします。
import csv

◆-- !! List !! --◆

=======================================
◆ List型のCSVを書き込む
=======================================


◆simpleなリスト形式

openの第二引数:  'w ' : 書き込み

import csv
sample=['name','Freddie', 'song', 'Rock you', 'year', '1977']

with open ('a.csv','w', newline='') as f:
    mySample = csv.writer(f, delimiter=",")
    mySample.writerow (sample)


print(mySample)  #<_csv.writer object at 0x0000000002EEAC50>

これを実行すると、実行ファイルと同じディレクトリに、以下のような a という名前のcsvファイルが作成される。事前に a というcsvファイルを作成しておく必要はない。




print(mySample) の実行結果は、#<_csv.writer object at 0x0000000002EEAC50> として、コンソールに表示されます。


◆List内にListを内包する形式

上記の例では、シンプルなリストを最初に定義しておきましたが、個別に 'row' 毎に記述して書き込むことも可能。

import csv
with open ('a.csv','w', newline='') as f:
     writer = csv.writer(f, delimiter=",")
     writer.writerow (['name','Freddie'])
     writer.writerow (['song','Rock you'])
     writer.writerow (['year','1977'])

実行すると、前回と同様に、a という.csvファイルが作成され、こんな感じのデータが書き込まれます。

name age
Freddie 24
title year
Bohemian Rhapsody 1974





(2)作成したCSVを以下のコードで1行ずつ再度、読みだす。
(コード:)
import csv
with open("a.csv","r") as f:
    reader=csv.reader(f)
    for line in reader:
        print(line)

(Output)
['name', 'age']
['Freddie', '24']
['title', 'year']
['Bohemian Rhapsody', '1974']

(コード:要素を指定して1行ずつ)
import csv
with open("a.csv","r") as f:
    reader=csv.reader(f)
    for line in reader:
        print(line[0])

(Output)
name
Freddie
title
Bohemian Rhapsody


(3) 読み込んだリストを新しいリストに格納してからprint
list()関数の使用

import csv
with open("a.csv","r") as f:
    reader=csv.reader(f)
    data=list(reader)
print(data)

(Output) リストを内包するリストが作られる。
[['name', 'age'], ['Freddie', '24'], ['title', 'year'], ['Bohemian Rhapsody', '1974']]

(4)辞書型に変換する(*これは大事なので後で詳述予定。)
*dict関数を使用
data=dict(reader)
print(data)
(Output) 辞書が作られる。
{'name': 'age', 'Freddie': '24', 'title': 'year', 'Bohemian Rhapsody': '1974'}
with文なしで
import csv
f = open('sample.csv', 'w')
writer = csv.writer(f, linetermination='\n')
writer.writerow(list)
writer.writerows(array2d)

f.close()  #開いたら忘れず閉じる。


例) test1.csvのデータ(value)をtest2.csvに書き込む

開いたcsvのデータを、別のcsvに書き込む。

readerメソッド)

import csv
with open("test1.csv","r") as csv_file:
    csv_reader = csv.reader(csv_file)

with open("test2.csv", "w") as new_file: <-ファイルが無ければ作成してくれる。
     csv_writer = csv.writer(new_file, delimiter='\t') #writerメソッド。delimiterは区切りを変更したければ。
        for line in csv_reader: <-csv_readerはイテラブル。writerは違う。 あたりまえだけど
            csv_writer.writerow(line)

*Listを1行、追加したい場合は、for文の代わりに、csv_writer.writerow(リスト名)を書けば良い。


=======================================
◆ List型のCSVを読み込む
=======================================
with文ありで
import csv
with open("start.csv","r", encoding='utf-8_sig') as f:  #windows encoding用の記述
 reader = csv.reader(f) #左のreaderは、variableで名前はなんでも良い。 csv.readerはmethod

   #この段階でprint(reader)とすると、読み込まれたレジストリの位置情報が格納されている。

   #この段階でreaderに格納されている値を確認したい場合、pirnt(list(reader))で表示できる。

 for line in reader:
    print(line)
 

    print(line[2])

openの第二引数:
r : 読み込み

==readerメソッドとDictReaderメソッド
 reader = csv.reader(f)の代わりに
 reader = csv.DictReader(f) とすると、1行目がkeyとして扱われる、

openで使えるオプション
   newline=""  :改行の自動処理

==read
これはイテレータです。
イテレータとは、「イテレータ(英語: Iterator)とは、プログラミング言語において配列やそれに類似するデータ構造の各要素に対する繰返し処理の抽象化である。」と書いてありますが、要は、For 文とかで一つずつ取り出さないと、値が読めないデータの塊りのようです。

但し、ここで読み込んだcsvの値をイテレータのまま、Jinjaに渡そうとすると、以下のようなエラーメッセジがでる。

pyファイル:
from flask import Flask, render_template
import csv
app = Flask(__name__)
@app.route('/')
def home():
    with open("sampleTest.csv","r", encoding='utf-8_sig') as f:
        reader = csv.reader(f)

    return render_template("sample01.html", passMessage=reader)
if __name__ == '__main__':
     app.run()

DOSのエラーメッセージ:
-level template code
    {% for post in passMessage %}
ValueError: I/O operation on closed file.

読み込んだ値をそのまま、別のファイルに渡すのは無理みたい。

そこで、リストに格納して、データを渡せるようにする。
記事: Python3 CSVを読み込んでリストに格納。 -イテレータの取り扱い


例)
import csv

# ファイルを読み込みモードでオープン
with open('sample.csv', 'r') as f:  # withでファイルを開くとファイルcloseの為の記述不要。

  reader = csv.reader(f) # readerオブジェクトを作成
  header = next(reader)  # 最初の一行をヘッダーとして取得。単にnext(reader)としても良い。

  print ''.join(header)  # ヘッダーをスペース区切りで表示
 
  # 行ごとのリストを処理する
  for row in reader:
    print ''.join(row)   # 1行ずつスペース区切りで表示
 
 word = "Good morning, Hello, Good night"
words = word.split(',')
with open('start.csv', 'w') as f:
    writer = csv.writer(f)

    writer.writerow

*next(reader)を2回書くと、上から2行がスキップされる。
  reader = csv.reader(f) # readerオブジェクトを作成
  next(reader)
  next(reader)

*csvで、値を区切るものをdelimeterと言いますが、これがあると読みにくかったりします。



◆-- !! Dictionary !! --◆

=======================================
◆ Dictionary型のCSVを書き込む
=======================================
DictReaderメソッド)

*空のcsv.fileをPython Appと同じディレクトリー内につくる。

test.py
import csv

with open('test.csv', 'w') as csv_file:
    fieldnames = ['Date','Name', 'Score']
    writer = csv.DictWriter(csv_file, fieldnames=fieldnames,lineterminator='\n')
   

    writer.writeheader()
    writer.writerow({'Date':'0117',''Name': 'Mike', 'Score': 90})
    writer.writerow({'Date':'0317', 'Name': 'Bob', 'Score': 95})

(rowが増えて、個別にrowやfilednameを記述するのが面倒なら、事前に辞書を作成し、
test_score=[
    {'Date':'0117','Name':'Mike', 'Score': 90},
    {'Date':'0317','Name':'Bob', 'Score': 95}
    ]

としておいて、

with open("a.csv",'w') as f:
   
    fieldnames = ['Date', 'Name','Score']
    writer=csv.DictWriter(f, fieldnames=fieldnames,lineterminator='\n')
    writer.writeheader()
    writer.writerows(test_score)

としても良い。



1行の書き込みは、writerow で良いけど、複数まとめてはwriterows になります。
拘ってますね。




# writer.はデータを格納しておく変数名なので、自由につければ良い。

#fieldnames=fieldnames と指定すると、Dictionaryの列の順番が保持される。
(fieldnamesは、自分で定義する変数です。)
#filenamesの定義は、  csv.DictWriter(csv_file, fieldnams=['Date','Name', 'Score'])と
 直接DictWriterのオプションとして指定することも可能。


これを実行すると、csvに以下のように書き込まれる。

Output in test.csv  file

Date,Name,Score
0117,Mike,90
0317,Bob,95

* 個別にrowやfilednameを記述するのが面倒なら、辞書型データを内包するリストを
  定義しておいて、csvに書き込むことも可能。
import csv
test_result=[{'Name': 'Mike', 'Score': 90},
            {'Name': 'Bob', 'Score': 95}]
with open('quick.csv', 'w') as csv_file:
    fieldnames = ['Name', 'Score']
    writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
    writer.writeheader()
    writer.writerows(test_result)

結果は上に同じ。

================
JSON ファイルについて
================
JSON形式のデータは、以下のようにKeyに対する値としてデータが入っているので、
Data = {
   "20200709": [
      {
         "ticker": "NGHC",
         "changes": 13.43,
         "price": "33.84",
         "changesPercentage": "(+65.80%)",
         "companyName": "National General Holdings Corp"
      },
      {
         "ticker": "ARRY",
         "changes": 17.69,
         "price": "46.57",
         "changesPercentage": "(+61.25%)",
         "companyName": "Array BioPharma Inc."
      },

 writer.writerowsに読み込ますデータは、
to_csv = Data[20200709]
なので、値までアクセスしておき、
    writer.writerows(to_csv)
で読み込ます。


◆------------------------------------------------------------------------------◆
もし、リストと辞書をつかわないで、以下のようにだらだら書くと、

import csv
test_score={'Date':'0117','Name':'Mike','Score':'90','Date':'0317','Name':'Bob', 'Score': 95}
with open("a.csv",'w') as f:
    fieldnames = ['Date', 'Name','Score']
    writer=csv.DictWriter(f, fieldnames=fieldnamesx,lineterminator='\n')
    writer.writeheader()
    writer.writerow(test_score)


Output:
 Date Name Score
317 Bob 95

と、最後の辞書のセットだけが書き込まれる。上書きされちゃうんですね。

◆------------------------------------------------------------------------------◆

(確認:読み込んでみる)

import csv
with open("a.csv","r") as f:
    reader = csv.reader(f) ←この例は辞書型内包のリストなので、csv.reader

    new_score=[]
    for line in reader:
        print(line)   # <-- ①
        new_score.append(line)
print(new_score) <-- ②

Output①:  csv.readerなのに辞書のkeyをちゃんと認識してくれている。
['Date', 'Name', 'Score']
['0117', 'Mike', '90']
['0317', 'Bob', '95']

Output②:
[['Date', 'Name', 'Score'], ['0117', 'Mike', '90'], ['0317', 'Bob', '95']]

いや、リストで囲まれてるからkeyを認識するわけではないみたい。

CSVに、以下の辞書を書き込んで、読み込んでみる。
test_score={'Date':'0117','Name':'Mike','Score':'90'}

with open("a.csv",'r') as f:
    reader = csv.reader(f)
 new_score=[]
   for line in reader:
          print(line) #output ①
             new_score.append(line)
print(new_score) #output ②


で、以下のようにkeyとvalueを分離してくれる。
但し、リストで返される。

Output ①
['Date', 'Name', 'Score']
['0317', 'Bob', '95']

output ②:
[['Date', 'Name', 'Score'], ['0317', 'Bob', '95']]

csvを読み込んだリストを作るとき、形式が変わってしまっているので注意が必要ですね。


==辞書型で読み込む。
import csv

with open("a.csv",'r') as f:
    reader = csv.DictReader(f)
    new_score=[]
   
    for line in reader:
        print(line)  
        new_score.append(line)
print(new_score)
Output①:
OrderedDict([('Date', '0317'), ('Name', 'Bob'), ('Score', '95')])
Output②:
[OrderedDict([('Date', '0317'), ('Name', 'Bob'), ('Score', '95')])]


csv.readerで読み込むか、csv.DictReaderで読み込むかは、読み込むデータの形式ではなく
読み込んだデータを、どの値で保持したいかの違いで使い分ける、のか?


-------------------------------------------------------------------------------------------------------

発展(1): test1.csvを読み込み、test2.csvに書き込む。

import csv

with open("test1.csv","r") as csv_file:
    csv_reader = csv.DictReader(csv_file)

with open("test2.csv", "w") as new_file:
     fieldnames =['column1', 'column2', 'column3']
     csv_writer = csv.DictWriter(new_file, fieldnames=fieldnames, delimiter='\t')
     csv_writer.writeheader()
       for line in csv_reader:  <-csv_readerはイテラブル。writerは違う。 あたりまえだけど。
            csv_writer.writerow(line)

-------------------------------------------------------------------------------------------------------

3. 辞書に追記
openの第二引数:  'a ' : 追記
'w'を指定すると上書きされるが、'a'を指定して書き込むと追記される。


        with open('quick.csv', 'a') as csv_file:
            fieldnames = ['area', 'original_area','category','answer']
            writer = csv.DictWriter(csv_file, fieldnames=fieldnames,lineterminator='\n')
            writer.writeheader()
            writer.writerow(questions)


areaoriginal_areacategoryanswer
ABCD
areaoriginal_areacategoryanswer
ABCD
areaoriginal_areacategoryanswer
1234

4. 削除

(1) Key による列(row)の削除

==1番最初のと同じ、こんなcsvが作成されていたとする。

test_score=[
    {'Date':'0117','Name':'Mike', 'Score': 90},
    {'Date':'0317','Name':'Bob', 'Score': 95}
    ]

with open("a.csv",'w') as f:
   
    fieldnames = ['Date', 'Name','Score']
    writer=csv.DictWriter(f, fieldnames=fieldnames,lineterminator='\n')
    writer.writeheader()
    writer.writerows(test_score)
import csv
test_score=[
    {'Date':'0117','Name':'Mike', 'Score': 90},
    {'Date':'0317','Name':'Bob', 'Score': 95}
    ]

with open("a.csv",'r') as f:
    csv_reader = csv.DictReader(f)
    modified_t=[]
    for line in csv_reader:
        del line['Date']  <- Key 全体を削除できる。
        modified_t.append(line)
print(modified_t)

Output:

[OrderedDict([('Name', 'Mike'), ('Score', '90')]),
 OrderedDict([('Name', 'Bob'), ('Score', '95')])]

(2)行(line)の削除

import csv
with open("a.csv",'r') as f:
    reader=csv.reader(f)
    new_r=[]
    for line in reader:
        new_r.append(line)
   
print(new_r) #output ①

new_r.pop(len(new_r)-1)  #List番号は0から始まるので1をマイナスしないと。
print(new_r) ♯Output ②
 #output ①
[ ['name', 'rank', 'score', 'record'],
  ['Justine', '1', '10', "['10', '20', '30']"],
  ['Puth', '2', '20', "['20', '30', '40']"],
  ['Shia', '3', '30', "['50', '60', '70']"]]

 #output ②
[ ['name', 'rank', 'score', 'record'],
  ['Justine', '1', '10', "['10', '20', '30']"],
  ['Puth', '2', '20', "['20', '30', '40']"]]

=======================================
◆ Dictionary型のCSVを読み込む
=======================================

上手く構成できなかったけど、もう、だいぶ書いてしまった。


参考)
- Parsing Names From a CSV to an HTML List  
https://www.youtube.com/watch?v=bkpLhQd6YQM&spfreload=5

0 件のコメント:

コメントを投稿