☆☆ 新着記事 ☆☆

2019年1月25日金曜日

Python CSVを扱う時のリストと辞書を研究する

Excelだと簡単な表の操作も、Pythonで扱おうとすると難しく感じます。 それは、データがチュートリアルに出てくる単純なリストや辞書ではないから。

「リストを内包するリスト」、「辞書を内包するリスト」、「リストを内包する辞書」、また更に、辞書を内包する、とか、どんどん構造が深くなっていきます。

そこで、リスト、辞書の表現形式とPythonのスクリプトの基本を確認しておきます。


PythonでCSVを扱う基本操作は、こちらを確認ください。

関連記事: Python 3でCSVファイルの操作

writer.writerows(array2d) <- 2元配列の使い方

<前提>

1. Listの書き込み、読み込み

(sample)
sample=['name','Freddie', 'song', 'Rock you', 'Year', '1977']

(書き込み)
 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)


(作成されたcsvの内容確認)

これで、' a.csv ' が作成される。

この a.csv を
1) text editorで開くと、

   name,Freddie,song,Rock you,Year,1977

という文字列になる。(あたり前ですが。)

2) excelで開く


要素が1つずつ、セルに格納されている。

読み込み

 このa.csvを読みだしてみる。

import csv
with open("a.csv","r") as f:
    reader=csv.reader(f)
    for line in reader:
        print(line)  # --①
   print(line[1]) # --②
Output
① ['name', 'Freddie', 'song', 'Rock you', 'Year', '1977']
記述したそのままですね。
② Freddie  
要素が取り出せます。

因みに、a.csvを以下のように2行に書いて①で再読み込みすると


IDEで1行ずつ表示させる。
import csv
with open("a.csv","r") as f:
    reader=csv.reader(f)
   
    for line in reader:
        print(line)

['name', 'Freddie', 'song', 'Rock you', 'Year', '1977']
['name', 'Charlie', 'song', 'Attention', 'Year', '2018']

 print(line[1])
で、以下の要素が取り出せる。
 'Freddie'
 'Charlie'



list()関数で、別のリストを作成して表示させる。

[['name', 'Freddie', 'song', 'Rock you', 'Year', '1977'], ['name', 'Charlie', 'song', 'Attention', 'Year', '2016']]
2次元リストになっている。

そこで、しつこいようだが、このリストをCSVに書き込んでみる。

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

a.csv を、テキスト・エディータで開くと、
"['name', 'Freddie', 'song', 'Rock you', 'Year', '1977']","['name', 'Charlie', 'song', 'Attention', 'Year', '2016']"

Excelで開くと
 
 
1つのセルに内包されるリストの要素が、全て1つの要素として格納されている。
これをしつこいようですが、再度、読み込む。
 
import csv
with open("a.csv","r") as f:
    reader=csv.reader(f)
    for line in reader:
        print(line)
        print(line[1])


Output:
["['name', 'Freddie', 'song', 'Rock you', 'Year', '1977']", "['name', 'Charlie', 'song', 'Attention', 'Year', '2016']"]
['name', 'Charlie', 'song', 'Attention', 'Year', '2016']

そのままですね。


2. 辞書の読み込み・書き込み


では、 前にCSVを変更した以下のように表示させるには、どうすれば良いか?




のように記述するのは、どうしたら良いか?

これと全く同じではないけど、利用目的を考えるとDictionaryなんでしょうね、


import csv
sample=[
    {'name':'Freddie', 'song':'Rock you', 'year': '1977'},
    {'name': 'Charlie', 'song': 'Attention', 'year': '2016'}
    ]
with open("a.csv",'w') as f:
    fieldnames = ['name', 'song','year']
    writer=csv.DictWriter(f, fieldnames=fieldnames)
    writer.writeheader()
    writer.writerows(sample)


 
*1行、空いてしまうので、後述のように、lineterminator='\n' をオプションで指定する。
 
 
辞書のvalueにリストも入れられる。
 
import csv
sample = [
    {'name': 'Justine', 'rank':'1', 'score':'10', 'record': ['10', '20', '30']},
    {'name': 'Puth', 'rank':'2', 'score':'20', 'record': ['20', '30', '40']},
    {'name': 'Shia', 'rank':'3', 'score':'30', 'record': ['50', '60', '70']},
    ]
with open("a.csv",'w') as f:
    fieldnames = ['name', 'rank','score','record']
    writer=csv.DictWriter(f, fieldnames=fieldnames,lineterminator='\n')
    writer.writeheader()
    writer.writerows(sample)

 
 
3. 辞書の読み込み
 
==csv.readerで読み込む。
import csv
with open("a.csv","r") as f:
    reader = csv.reader(f)
    for line in reader:
        print(line)
['name', 'rank', 'score', 'record']
['Justine', '1', '10', "['10', '20', '30']"]
['Puth', '2', '20', "['20', '30', '40']"]
['Shia', '3', '30', "['50', '60', '70']"]
 
[['name', 'rank', 'score', 'record'], ['Justine', '1', '10', "['10', '20', '30']"], ['Puth', '2', '20', "['20', '30', '40']"], ['Shia', '3', '30', "['50', '60', '70']"]]
 
==csv.DictReaderで読み込む。
 
import csv
with open("a.csv","r") as f:
    reader = csv.DictReader(f)
   b=[]
    for line in reader:
        print(line)
        b.append(line)
print(b)

OrderedDict([('name', 'Justine'), ('rank', '1'), ('score', '10'), ('record', "['10', '20', '30']")])
OrderedDict([('name', 'Puth'), ('rank', '2'), ('score', '20'), ('record', "['20', '30', '40']")])
OrderedDict([('name', 'Shia'), ('rank', '3'), ('score', '30'), ('record', "['50', '60', '70']")])

[OrderedDict([('name', 'Justine'), ('rank', '1'), ('score', '10'), ('record', "['10', '20', '30']")]), OrderedDict([('name', 'Puth'), ('rank', '2'), ('score', '20'), ('record', "['20', '30', '40']")]), OrderedDict([('name', 'Shia'), ('rank', '3'), ('score', '30'), ('record', "['50', '60', '70']")])]
 

 
ところで、こんな数字をValueとしてもつ、CSVファイルがあったとする。
 
 
 
textで開くとこんな感じ。
 
question,answer,option1,option2,option3,tip
1?,1,1,2,3,one
2?,2,2,3,4,two
3?,3,3,4,5,three
4?,4,4,5,6,four
5?,5,5,6,7,five
 
 
これを、Pythonのcsvモジュールを使って読み込むと、IDEでのprint outは、こんな感じ。
 
[{'question': '1?', 'answer': '1', 'option1': '1', 'option2': '2', 'option3': '3', 'tip': 'one'}, {'question': '2?', 'answer': '2', 'option1': '2', 'option2': '3', 'option3': '4', 'tip': 'two'}, {'question': '3?', 'answer': '3', 'option1': '3', 'option2': '4', 'option3': '5', 'tip': 'three'}, {'question': '4?', 'answer': '4', 'option1': '4', 'option2': '5', 'option3': '6', 'tip': 'four'}, {'question': '5?', 'answer': '5', 'option1': '5', 'option2': '6', 'option3': '7', 'tip': 'five'}]
 
text形式に変換される。 
 
従って、このままではintegerとして扱えない。
 
a=[
    {'question': '1?', 'answer': '1', 'option1': '1', 'option2': '2',
     'option3': '3', 'tip': 'one'},
    {'question': '2?', 'answer': '2', 'option1': '2', 'option2': '3',
     'option3': '4', 'tip': 'two'}
    ]
b=a[0][option1]+a[1][option1]
print(b)
NameError: name 'option1' is not defined
 
となるのに対し、
a=[
    {'question': '1?', 'answer':'1','option1':1,'option2': '2',
     'option3': '3', 'tip': 'one'},
    {'question': '2?','answer': '2','option1':2,'option2': '3',
     'option3': '4', 'tip': 'two'}
    ]
のように、要素のValueが数字であれば、計算ができる。
 
b=a[0]['option1']+a[1]['option1']
print(b)  #Output: 3

 
因みに、enumerate()で辞書にindex番号をつけると、integer形式の数字が付与される。
keyに紐づくbalueの形式には影響しない。
 
b=dict(list(enumerate(a,start=1)))
 
{1: {'question': '1?', 'answer': '1', 'option1': 1, 'option2': '2', 'option3': '3', 'tip': 'one'}, 2: {'question': '2?', 'answer': '2', 'option1': 2, 'option2': '3', 'option3': '4', 'tip': 'two'}}


0 件のコメント:

コメントを投稿