Pythonのメモ帳

numpy, pandas, tensorflow を使いこなすための忘備録

ダイアログボックスでファイル名を指定したい(Windows/Macでコードが違う)

データを取り込む時にはファイル名を指定する。
pd.read_csv()でも np.loadtxt()でもそう。

でファイル名を指定するのにコードをいちいち書き換えたくないので、
ダイアログボックスを使う方法を調べた。

調べたらtkinterというライブラリを使うみたいだが、これがPython2系とPython3系でコードが色々と違うみたい。Python3系向けにここでメモ。

OSが違うとコードの書き方が変わるので注意。

 

windowsの場合

import tkinter as tk
import tkinter.filedialog as tkdialog
import os

root  = tk.Tk()
fname = tkdialog.askopenfilename(filetypes=[('data files','*.csv;*.txt')],initialdir=os.getcwd())
root.withdraw()

引数filetypesでダイアログボックスに表示される拡張子を制限指定できる。ここではcsv,txtに絞ってるけど、すべて表示したければ,

filetypes=[('all files','*.*')]

とすればOK。

 

Macの場合

macOSwindowsではfiletypesの書き方が違うようで、上のコードではファイルが指定できなかった。こう書けば大丈夫だった。

root  = tk.Tk()
fname = tkdialog.askopenfilename(filetypes=[("csv files","*.csv"),("txt files","*.txt")],initialdir=os.getcwd())
root.withdraw()

ただ、windowsの時のように全てのファイルが選択できるようにする方法はわかりません。

 

 

最後に、どちらの場合も一緒にimportしているosは現在のディレクトリを取得するのに使っているだけなので不要なら引数の部分と一緒に削除してOK。

pandas の append処理で行ラベル(index番号)がおかしくなった時に行ラベルをリセットする

pandas で append処理(2つのDataFrameを縦に連結)した時、行ラベル(index番号)は順番通りにならなくなる。

 例えばこう。

import pandas as pd
import numpy as np

data = range(10)
data = np.array(data).reshape([5,2])
df1 = pd.DataFrame(data,columns=['col0','col1'])
df2 = pd.DataFrame(data,columns=['col0','col1'])
df  = df1.append(df2)
print(df)

Out:

  col0 col1
0 0 1
1 2 3
2 4 5
3 6 7
4 8 9
0 0 1
1 2 3
2 4 5
3 6 7
4 8 9

 

 

df.loc()など行ラベルを参照する処理でこれがエラーを招くことがある。

そんな時は行ラベルを割り振り直すことで対処できる。

reset_index()を使う。

df = df.reset_index(drop=True)

ちゃんと返り値を保持することを忘れずに。

2つの文字列配列の要素同士を連結する(文字列配列の足し算)

numpyでは配列(行列)の計算が簡単にできる。これは要素が数字の場合だけでなく、ありがたいことに文字列の場合にも使える。文字列の場合にできる計算は足し算(文字列の連結)だけで、使うこともあまりないけど地味にありがたい。

import numpy as np

array1 = np.array([['a', 'b', 'c'],['a', 'b', 'c']], dtype=object)
array2 = np.array([['1', '2', '3'],['1', '2', '3']], dtype=object)
print(array1 + array2)
出力: array([['a1', 'b2', 'c3'],
['a1', 'b2', 'c3']], dtype=object)

 

 

だだし、配列の型の設定をしないとエラーになるので注意。下のように引数の dtype=object を除くとエラーになる。

array1 = np.array([['a', 'b', 'c'],['a', 'b', 'c']])
array2 = np.array([['1', '2', '3'],['1', '2', '3']])
print(array1 + array2)

出力: TypeError: ufunc 'add' did not contain a loop with signature matching types dtype('<U1') dtype('<U1') dtype('<U1')

 

 

もちろん後から型を変換しても大丈夫。

array1 = np.array([['a', 'b', 'c'],['a', 'b', 'c']])
array2 = np.array([['1', '2', '3'],['1', '2', '3']])
print(array1.astype(object) + array2.astype(object))
出力: array([['a1', 'b2', 'c3'],
['a1', 'b2', 'c3']], dtype=object)

  

 

 

 

 

DataFrameからリストやnumpy.ndarrayへの変換

DataFrameからnumpy.ndarrayへの変換

.valuesと付け足すだけ。pandas.Seriesの場合も同様の処理で変換が可能。

import numpy  as np
import pandas as pd

dataframe = pd.DataFrame([[1, 2, 3], [4, 5, 6]], dtype=int)
array1     = dataframe.values.tolist()
print(array1, type(array1))

series = pd.Series([11, 12, 13], dtype=int)
array2  = series.values.tolist()
print(array2, type(array2))

 

DataFrameからリストへの変換

.valuesで一度numpy.ndarrayにしたのち、numpy.tolist()を使う。

list1 = dataframe.values.tolist()
print(list1, type(list1))

list2 = series.values.tolist()
print(list2, type(list2))

 

ndarrayからDataFrameへの変換

念のため逆も書いておく。

df_new     = pd.DataFrame(array1)
series_new = pd.Series(array2)

 

リストからDataFrameへの変換
df_new     = pd.DataFrame(list1)
series_new = pd.Series(list2)

 

 

 

pandasでcsvファイルを読み込む際にあえてカラム(列)を分けない

ファイルの読み込みはいくつか方法があることは前回の記事に書いた。

spcx8.hatenablog.com

 

読み込んだ後の処理を考えると、numpyやpandasで読みたい。でも中身が文字列を含む場合、numpyは使えないのでpandasで読むことになる。

困るのは読み込む対象のファイルの形式が整っていない場合。列数が揃っていない、特に先頭行の列数が少ない場合に読み込みエラーが起こる。

そんな場合は、あえて列を分けずにn行1列のデータフレームとして読み込む方法もある。以下のように引数の delimiter で改行コード'¥n'を指定すればOK。

import pandas as pd

df = pd.read_csv('data.txt', skiprows=0, header=None, delimiter='¥n', index_col=None)

列の分割はデータを読み込んだ後に必要な箇所だけ行う。DataFrameからリストやnumpy.ndarrayへの変換はいくつかの方法がある。それはまた別の機会に。

 

 

 

 

 

csvファイルやexcelファイル(xls, xlsx)を読み込む

 csvファイルやexcelファイル(xls, xlsx)を読み込む場合のコードはいくつかあるのでまとめておく。

 

(1) 標準ライブラリのcsvを使う

import csv

with open('data.txt', 'r', encoding='utf-8') as f:
dataReader = csv.reader(f, lineterminator='\n')
for row in dataReader:
    print(row)

第二引数を'rb'とすればバイナリファイルが扱える。
追加のライブラリが不要。.txt / .csvのどちらも読み込み可能。
空白や文字列があってもOK。

ただし、中身を取り出すのにfor構文が必要で不便。

 

(2) numpy を使う

import numpy as np

data = np.loadtxt('data.txt', delimiter=',', skiprows=0)

np.ndarray型で読み込む。.txt / .csvのどちらも読み込み可能。
ただし,空白や文字列があるとエラーになる。
大抵は先頭行が項目名になってい流けど、その場合は引数をskiprows=1として1行スキップすればOK。

またはgenfromtxt()を使う。空白や文字列があるとnanにしてくれる。

data = np.genfromtxt('data.txt', delimiter=',')

 

 (3) pandasを使う

import pandas as pd

df = pd.read_csv('data.txt', skiprows=0, header=0, index_col=0)

pandas.Dataframe型で読み込む。.txt / .csvのどちらも読み込み可能。
空白や文字列があってもOK。

引数がたくさんあって色々調整できる

header : 項目名に使う行を指定。Noneとしておくと項目名がなくなり、先頭行からデータとして読み込む

index_col:行名として使う列を指定。

その他の引数は省略。 下は関連記事へのリンク。

spcx8.hatenablog.com

 

 

excelファイル(xls, xlsx)を読み込みたい場合は、read_excel()を使う。

df = pd.read_excel('data.xls', skiprows=0, header=0, index_col=2)

 詳しくは別記事で。

 

 

 

 

配列内の各要素に含まれる特定の文字列を置換・削除する方法

文字列の置換はreplace()を使う。

string = 'abcde'
string_new = string.replace('a', 'A')
print(string_new)

出力: 'Abcde'

 

これが使えるのは単独の文字列だけで、配列(各要素が文字列になっている配列)には使えない。

str_list = ['abcde','abcde']
str_list_new = str_list.replace('a', 'A')

これを処理しようとするとエラーになる。
AttributeError
: 'list' object has no attribute 'replace'

 

なので以下のように、配列を一旦単独の文字列に変換し、replace()で置換、のちに配列に戻すという処理をする。

str_list = ['abcde','abcde']
string = ",".join(str_list)
string_new = string.replace('a', 'A')
str_list_new =  string_new.split(",")
print(string_new)

出力: ['Abcde', 'Abcde']

 

ちなみに、このreplace()の2番目の引数を空白('')にしておけば、削除の処理ができる。

string_new = string.replace('a', '')

 

 

 WEB/EC専門の転職支援サービス【サポタント】