プログラミング入門II
2024.07.17
ファイル処理

Back to index page


7月10日の授業はJR山陰線の運休により休講となりましたので,その回の内容を今回17日に行います.なお,次週の内容は7月24日としていますが,オンデマンド形式に現時点ではする予定です.17日までには確定させますので,案内には注意していてください.


  1. 本日の作業内容

  2. 前々回の宿題について
  3. 前々回の宿題の解答例が間違っていました.現在正しいものに変更していますが,filter 関数で頻度を計算した際に大きい方の数値以下とするべきところを未満としていたので,データに漏れが出てしまいました.すみませんでした.

    また,その結果,例示した実行例の頻度の和が1000になっていなかったので,結構な数の人が1000回繰り返しとしていなかったことになりました.このような場合に何を信用して何を間違っていると判断するのは,学生さんとしては立場上難しいかもしれませんが,中途半端な回数繰り返すというあまり無い指示をすることは通常無いので,問題文の1000回の方をあくまで基準にしてプログラムをしてほしかったところです.ある程度の救済はしますが,あてにはしないでください.ごめんなさい.

  4. 前回の宿題について

    今回は try 文による例外処理でしたので,さすがにエラーが出るものが無くて,そこは安心しました.また,形式的な間違いもほとんどなくて,そこもとてもうれしく思いました.あと少しですので,この調子で頑張りましょう.

    出力時番号間違い: b2338

    以下は例によって問題のあるプログラムの例です.参考にしてください.

    import random
    
    print('Student number: s******')
    print('')
    
    try:
        from random import randint as ra
    

    こちらの解答用紙の準備の問題かもしれませんが,import 文が重複しています.

    import random
    
    print('Student number: s******')
    print('')
    
    import random
    
    import random
    

    こちらは何回 import するんでしょうかね.

    day = (d_list[0][ri(0, 1)], d_list[1][ri(0, 1)], d_list[2][ri(0, 1)])
    

    このように繰り返しでできることを手作業で一つ一つやるのはあまり歓迎しません.

    x = random.randint(0,1)
    y = random.randint(0,1)
    z = random.randint(0,1)
    
    a_list = [d_list[0][x],d_list[1][y],d_list[2][z]]
    

    上のようなものも多くみられました.いちいち変数を置かなくても,できるはずです.

    year = d_lst[0][random.randint(0, 1)]
    month = d_lst[1][random.randint(0, 1)]
    day = d_lst[2][random.randint(0, 1)]
    
    date_lst = [year, month, day]
    

    上も同様ですね.

    d_list2 = []*3
    for i in range(3):
        b = d_list[i][a]
        d_list2.append(b)
    print('.'.join(d_list2))
    

    上のものは処理は間違っていませんが,Python ではなるべく for 文を使わなくてもいいようにさまざまな関数やメソッドが用意されていますし,内包表記などもあるので,特に必要のない for 文で何行も使うのは Python 的ではありません.

    try:
        from random import randint as ran
        lst = [None] * 3
        for i in range(0, 3):
            lst[i] = d_list[i][ran(0, 1)]
    
        else:
            day = '-'. join(lst)
            print(day)
    
    except TypeError:
        print('Found int in str')
        day = '.'. join (map(str, lst))
        print(day)
    

    なんで結合文字列が違うんですかね?

    Student number: s******
    
    2024-7-3
    
    
    ------------------------
    
    Student number: s******
    
    Found int in str
    2024.7.3
    
    
    ------------------------
    

    try:
        d_list = [[2024, '2024'], [7, '7'], [3, '3']]
        lst = [d_list[0][rr(0,1)],d_list[1][rr(0,1)],d_list[2][rr(0,1)]]
        ''.join(lst)
       
    except TypeError:
        print('Found int in str')
        lststr = [str(n) for n in lst]
        '.'.join(lststr)
        print(*lststr)
    

    try 文の中に print が無いので,正常に文字列ができた場合に表示しません.

  5. 前回の復習

    例外処理について学習しました.実際に業務で使用するソフトはそう簡単にエラーでクラッシュしてはいけないので,想定されるエラーについて例外処理をきちんと記述しておくことは重要です.そのため一番簡単な try 文を体験しました.

  6. ファイル処理

    今回はファイル処理です.実際に実験などで得られたCSVファイルを読み込んで処理したり,計算結果をCSVファイルとして書き出したりすることは頻繁に行われることです.今回はCSV形式のテキストファイルについての読み込みと書き出しについて学習します.

    CSV とは Comma Separeted Value の略で,カンマ(コンマ)で区切られたデータ群のことです.ただし,区切り記号はカンマ以外にもスペースやタブなどが使われることもよくありますし,データを2重引用符 " で括る方式と括らない方式など,いくつかバリエーションもあります.今回はデータテキストはそのまま,区切り記号はカンマに限定して作業します.
    CSVデータの扱い

    Python は現在機械学習などを始めとしてデータ処理に多く利用されています.この分野では処理したデータをCSVファイルとして保存したり,CSVファイルを読み込んで処理したり,という作業が多くなります.そのため,Python には pandas や NumPy というデータ解析に便利なライブラリやツールが準備されていますが,今回は標準で用意されている CSV モジュールを使った方法を学習しましょう.

    1. モジュールの読み込み

      次のように import 文を用意します.

      import csv
      

    2. with 文によるファイル読み込み

      以下のような内容のデータが numbers.csv というファイル名でカレントディレクトリにあるとするとき,そのデータを読み込んで numbers というリストに保存する処理を考えます.

      1,2,3,4
      5,6,7,8
      

      教科書 p.360 にある with 文を使用して以下のようにしてみます.

      import csv
      
      with open('numbers.csv', 'r') as f:
          data = csv.reader(f)
          numbers = [n for n in data]
          
      print(numbers)
      
      f.close()
      

      使用するエディタによって色分けなどが違いはしますが,上のソースですと,色が付いている部分が予約語や関数です.それ以外の部分は自分で適当に名前をつけてよい変数やリストです.

    3. 読み込みデータの数値化

      先程のコードを実行すると,出力結果が以下のようになったはずです.

      [['1', '2', '3', '4'], ['5', '6', '7', '8']]
      

      ここで,reader という関数がデータを行単位で読み込んでくれています.

      データはちゃんと読み込めましたが,数値はシングルクオート ' ' で囲まれていますので,文字列です.計算などで使用するためには数値でないと困ります.

      EXCEL で読み込んだ場合はテキストでも自動で数値化してくれるので計算に使用できます.
      教科書 p.36 で int 関数が紹介されていますが,それを使用することで整数に変換することができます.ということで,数値化してみましょう.

      import csv
      
      with open('numbers.csv', 'r') as f:
          data = csv.reader(f)
          num_txt = [n for n in data]
          
      numbers = [[int(num_txt[i][j]) for j in range(0,4)] for i in range(0,2)]
          
      print(numbers)
      
      f.close()
      

      上のソースの中では,7行目のリスト numbers の作成における内包表記表現の添字 i と j に注意してください.内包表現では内側のリストの添字を j とし,外側のリストの添字を i とすることが慣例ですので,まず j についての値を操作し,次に外側で i についての操作を行っています.

    4. データ書き込み

      numbers というリストは2次元のリストになっていますが,内側のリストの和を要素として持つ num_sum というリストを作り,それを num_sum.csv というファイルに書き込んで保存することを行ってみましょう.

      import csv
      
      with open('numbers.csv', 'r') as f:
          data = csv.reader(f)
          num_txt = [n for n in data]
          
      numbers = [[int(num_txt[i][j]) for j in range(0,4)] for i in range(0,2)]
          
      num_sum = [sum(numbers[i]) for i in range(len(numbers))]
      
      with open('num_sum.csv', 'w') as ff:
          save_data = csv.writer(ff)
          save_data.writerow(num_sum)
      
      f.close()
      ff.close()
      

      再び with 文が登場しますが,今回は書き込みです.writer() 関数を使用しますが,1行書き込む writerow で書き込んでいます.

      書き込むデータが複数行に渡るときは最後の行は writerows() を使います.
  7. 演習

    今回の演習問題です.

  8. 宿題

    いつものようにレポート提出システムを利用します.授業当日の18:00から閲覧可能で,締切りは23日火曜日の10:00です.

  9. 次回の予習範囲

    次回もファイル処理です.教引き続き科書のp.354-373の範囲を学習しますので,予習をしてきてください.


目次ページに戻る