LoginSignup
6
12

More than 3 years have passed since last update.

pythonでスペース区切りのデータをcsvに変換する

Last updated at Posted at 2019-07-04

Pythonの標準モジュールreを用いて以下のようにスペースで区切られたデータをカンマ区切りのcsvファイルに変換します。

変換前
datetime  data1 data2
2019-01-01 15 25
2019-01-02  20 30
2019-01-03  25 40
変換後
datetime,data1,data2
2019-01-01,15,25
2019-01-02,20,30
2019-01-03,25,40

環境

  • Ubuntu16.04(WSL1)
  • Python3.6

pythonの標準モジュールしか利用していないので、たいていのpython環境でも問題なく動作すると思います。
実行はLinuxのshellからを行っています。(最近ではWindows環境でもWindows Subsystem for Linux等を使えば容易にLinux環境を構築することができるようになってきました。)

プログラムの作成

モジュールのインポート

mkcsv.py
import re
import sys

reはpythonで正規表現を扱うモジュールです。またsysはコマンドライン引数を指定してpythonにスペース区切りのファイルを渡すために利用します。

変換の準備

スペース区切りをカンマ区切りに変換するために正規表現の文字列のパターンと、入力するファイル、出力するファイルを準備します。

mkcsv.py
pattern=re.compile(' +') #' +'で一文字以上のスペースを正規表現のパターンとして定義
ifile=sys.argv[1]        #入力するファイル名をコマンドライン引数から受け取る
fout=open('c'+ifile.split('.')[0]+'.csv','tw') #出力ファイル名を入力ファイルから命名してopen

sys.argv[0]は実行ファイル名自体が返されます。

入力ファイルがtest.txtであった時、出力ファイルはctest.csvとなります。

入力ファイルを一行ずつ読み込んで出力ファイルに書き込み

mkscv.py
with open(ifile,'tr') as fin:
    for iline in fin:
        fout.write(pattern.sub(',',iline)) #一文字以上のスペースをカンマに置換
    ofile.close()

入力ファイルはwithで自動的に閉じられますが出力ファイルは自分で閉じておく必要があります。
コメントで教えていただきましたが入力ファイルと出力ファイルともにwithでまとめて記述することができるようです。

with open(ifile,'tr') as fin \
     open('c'+ifile.split('.')[0]+'.csv','tw') as fout:

追記:csvモジュールを使う

コメントで指摘いただいた通りcsvモジュールを使った方が圧倒的に適切です。
コードを引用させていただきます。

mkcsv.py
import csv
import sys

assert len(sys.argv) == 2
fname_in = sys.argv[1]
fname_out = 'c{}.csv'.format(
   ''.join(fname_in.split('.')[:-1])
)

with open(fname_in, newline='') as fin,  \
       open(fname_out, mode='w', newline='') as fout:

   reader = csv.reader(fin, delimiter=' ', skipinitialspace=True)
   writer = csv.writer(fout)

   writer.writerows(reader)

コード全体(非推奨)

mkcsv.py
#! /usr/bin/python3
import re
import sys
pattern=re.compile(' +') 
ifile=sys.argv[1]       
ofile=open('c'+ifile.split('.')[0]+'.csv','tw') 
with open(ifile,'tr') as fin:
    for iline in fin:
        ofile.write(pattern.sub(',',iline))
    ofile.close()

シェバン行にpythonパスを書いておくと直接ファイルを実行できます。環境に応じて変更してください。

実行

$ python3 mkcsv.py test.txt 

シェバン行を書いた場合

$ ./mkcsv.py test.txt

(個人的に)よく使うコマンドなので~/bin下にmkscv.pyを置いてパスを通しておくと便利です。

この場合どこのディレクトリからでもmkcsv.pyが実行できます。

$ mkcsv.py test.txt

補足1

上述のコードはカレントディレクトリにあるファイルにしか正常に動作しません。

入力ファイルからディレクトリのパスとファイル名に分離したりするとより汎用性を高められるかもしれません。

補足2

これくらいの置換ならわざわざpythonで書くよりもシェルスクリプトとawkとかsedを組み合わせて作った方がいいかもしれません。

以下awkを使って書いたコードです。

#! /bin/bash
filename=$(echo "$1" | awk 'BEGIN{ FS ="."}{ print $1}')
 awk -v OFS="," '{$1=$1; print $0 }' $1 > c"$filename".csv
rm $1
6
12
6

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
12