月別アーカイブ: 2021年2月

現在時刻をファイル名にして、データフレームをエクセルファイルとして保存する方法

pythonのpandasのデータフレームであれこれ処理した結果をエクセルファイルに保存したいことがあります。コードを実行するたびに名前を書き換えるのも大変なので、ファイル名は現在時刻を取得して使うことにします。

 

from datetime import datetime
from pandas import DataFrame

dic = {'numbers':[1,2,3]}
df = DataFrame(dic)

t = datetime.now()
current_time = t.strftime("%Y%m%d_%H%M%S")
df.to_excel(current_time+'_test.xlsx')

上のコードを実行すると、20210131_224944_test.xlsxというファイルが生成しました。エクセルで開くと中身は、

  numbers
0 1
1 2
2 3

 

 
となっていました。

pythonのリストや、辞書の中のリストの中の重複する要素の数を数える方法

太郎くんがバイト先のレストランで6人の客がいるテーブルで注文を受けたところ、コーヒー’, ‘紅茶’,’コーヒー’, ‘オレンジジュース’, ‘紅茶’,’コーヒー’でした。花子さんは、何がいくつあったかをpythonでわかりやすく集計したいと思いました。どんなコードを書けばよいでしょうか?

from collections import Counter
import pandas as pd
from pandas import DataFrame

飲み物注文リスト=['コーヒー', '紅茶','コーヒー', 'オレンジジュース', '紅茶','コーヒー']
個別アイテム数 = Counter(飲み物注文リスト)
df = pd.DataFrame.from_dict(個別アイテム数, orient='index').reset_index()
df = df .rename(columns={'index':'飲み物', 0:'数'})
df

上のようなコードを実行したところ、

  飲み物
0 コーヒー 3
1 紅茶 2
2 オレンジジュース 1

という結果が得られました。花子さんは、飲み物だけでなくメインディッシュの注文に関する情報も持っていました。メインディッシュに関しても、同様に集計するコードはどう書けるでしょうか。ただし、オーダーはpythonの辞書(dictionary)の形式で書かれているものとします。

オーダー={‘飲み物’:[‘コーヒー’, ‘紅茶’,’コーヒー’, ‘オレンジジュース’, ‘紅茶’,’コーヒー’],
‘メイン’:[‘ピザ’,’ピザ’,’ピザ’,’ピザ’,’パスタ’,’グラタン’]}

個別アイテム数 = Counter(オーダー['メイン'])
df = pd.DataFrame.from_dict(個別アイテム数, orient='index').reset_index()
df = df .rename(columns={'index':'食べ物', 0:'数'})
df

上のコードを実行してみると、

  食べ物
0 ピザ 4
1 パスタ 1
2 グラタン 1

 と集計できました。めでたし、めでたし。

 

参考

  1. Transform a Counter object into a Pandas DataFrame (StackOverFlow)

 

pythonで「辞書の配列」を作成する方法

pythonのpandasのデータフレームは表タイプのデータ処理を行うのに便利ですが、列の長さが揃っている必要があります。列の長さ(要素の数)がバラバラの場合には、辞書の配列のほうが便利ということもあるかもしれません(多分)。

‘のびた’,’すねお’, ‘しずか’,’わかめ’,’かつお’,’ドラえもん’,’しんのすけ’,’まるこ’といった人々がいたときに、彼らを3組のクラスに振り分けることを考えます。あとあとの事を考えて、辞書の配列を作成して、振り分けを行うには、どんなコードを書けばよいでしょう?

クラス数 = 3
dictlist = [dict() for x in range(クラス数)]

for i in range(クラス数):
dictlist[i] = {'氏名': []}

人びと=['のびた','すねお', 'しずか','わかめ','かつお','ドラえもん','しんのすけ','まるこ']

for k in range(len(人びと)):
dictlist[k%クラス数]['氏名'].append(人びと[k])

dictlist

上のコードを実行した結果は、

[{'氏名': ['のびた', 'わかめ', 'しんのすけ']},
 {'氏名': ['すねお', 'かつお', 'まるこ']},
 {'氏名': ['しずか', 'ドラえもん']}]

 

となり、3組に振り分けることができました。クラスの人数にばらつきがあります。

上のタスクみたいに、リストの要素に関して繰り返し処理をする場合には、リストの要素のインデックスと要素の中身そのものの両方がが欲しい場合が頻繁にあります。 その場合には、enumerateという関数が便利。上と同じ処理をenumerateを使って書けば、同じ処理が、

for k, person in enumerate(人びと):

dictlist[k%クラス数]['氏名'].append(person)

となります。

 

参考

  1. How can I create an array/list of dictionaries in python? (stackoverflow)

 

 

クラス数 = 3
dictlist = [dict() for x in range(クラス数)]

for i in range(クラス数):
dictlist[i] = {'氏名': []}

人びと=['のびた','すねお', 'しずか','わかめ','かつお','ドラえもん','しんのすけ','まるこ']

for k in range(len(人びと)):
dictlist[k%クラス数]['氏名'].append(人びと[k])

dictlist

 

参考

https://stackoverflow.com/questions/2397754/how-can-i-create-an-array-list-of-dictionaries-in-python

pythonの辞書(dictionary)の配列を作成する方法

pythonのモジュールpandasの中にあるDataFrameはエクセルなどの表の処理に便利ですが、各々のカラムの長さ(要素の数)が同じでないといけないという制約があるようです。そのため、要素の数などに制限がないようにと、辞書(dictionary)の配列を作ることを考えましたが、やり方がわからずネットで検索した結果、やり方が紹介されているのを見つけました。

  1. How can I create an array/list of dictionaries in python? (stackoverflow)
dictlist = [dict() for x in range(10)]

と簡単に10個の辞書からなる配列が作れました。

Python DataFrameでixを使おうとするとエラーになる件

Python pandas DataFrameを使っていて、セルを指定する方法がわからずネットで拾ったサンプルコードを使おうとすると、AttributeError: ‘DataFrame’オブジェクトには属性 ‘ix’がありませんというエラーを食らいました。

ixを使ったサンプルコードを頻繁に見かけるのですが、どうやらこれは廃止されたようです。 pandasのバージョンを気にする必要がありそう。ixとかlocとかilocとかで頭が混乱していたのですが、わかりやすい説明がありました。

  1. pandas の loc、iloc、ix の違い – python(コード7区)

DataFrameの行・列を指定する方法として、

行ラベル、列ラベルを使った指定方法⇒ loc

行の番号や列の番号を使った指定方法⇒iloc

ラベルや番号を使った指定方法⇒ix

ということだそうです。そして、pandas バージョン0.20.1 では、.ixインデクサが deprecatedになったそう。

  1. Pandas メジャーアップデート(0.20.1)の要点〜高速 I/O、集約関数強化など(2017-05-11 luggage baggage)
  2. Starting in 0.20.0, the .ix indexer is deprecated, in favor of the more strict .iloc and .loc indexers. (pandas.pydata.org)

データフレームの中から特定の文字を含む行を抽出する

データフレームの中から特定の文字を含む行を抽出する

# 特定の名前を探す練習スクリプト
import pandas as pd

df=pd.DataFrame({'名前':['太郎','次郎','三郎'],'研究種目':['若手研究','基盤研究(C)','若手研究']
                 ,'総額':[360,350,480]})

print(df,'\n')

mask = df.applymap(lambda x: '三郎' in str(x))

print (mask)

df1 = df[mask.any(axis=1)]

print('\n', df1)

上のコードを実行した結果は、以下のようになります。

   名前     研究種目   総額
0  太郎     若手研究  360
1  次郎  基盤研究(C)  350
2  三郎     若手研究  480 

      名前   研究種目     総額
0  False  False  False
1  False  False  False
2   True  False  False

    名前  研究種目   総額
2  三郎  若手研究  480

pythonでのエラー ValueError: Cannot mask with non-boolean array containing NA / NaN valuesへの対処法【解決】

pythonのpandasのデータフレームの特定のカラムの中である文字列を含むものだけ取り出したいと思いました。

df_文字列= df[df[‘特定のカラム名’].str.contains(‘文字列’)]

というコードを実行したところ、

ValueError: Cannot mask with non-boolean array containing NA / NaN values

というエラーになりました。このエラーの原因は何かというと、カラムの中に「空欄」が存在していたからなんですね。

以下のようにNAを無視するように na=Falseを付け加えたら、

df_文字列 = df[df[‘特定のカラム名’].str.contains(‘文字列’, na=False)]

エラーを回避できました。

この手のエラーは、空欄を含むスプレッドシートをデータフレームとして読み込んで何か処理をしようとするときには必ず遭遇してしまうと思います。空欄に関しては、何らかの例外処理が必要ということですね。