pandas.DataFrame.empty
具体的には以下のようになります。
-
False を返す場合
- DataFrameに一つでもデータ(要素)が存在する場合。
- たとえDataFrame内のすべての要素が
NaN
(Not a Number) であっても、データが存在するとみなされるため、empty
はFalse
を返します。すべての要素がNaN
のDataFrameが本当に「空」であると見なしたい場合は、dropna()
メソッドでNaN
を削除してからempty
を確認する必要があります。
-
- DataFrameにデータがまったく含まれていない場合(行も列もゼロの場合)。
- 列は定義されているが、行が一つもない場合。
- 行は定義されているが、列が一つもない場合。
使用例
import pandas as pd
import numpy as np
# 1. 空のDataFrame
df_empty = pd.DataFrame()
print("空のDataFrame:")
print(df_empty)
print(f"df_empty.empty: {df_empty.empty}") # True を返す
print("-" * 30)
# 2. 列は定義されているが、行がないDataFrame
df_cols_only = pd.DataFrame(columns=['A', 'B', 'C'])
print("列は定義されているが、行がないDataFrame:")
print(df_cols_only)
print(f"df_cols_only.empty: {df_cols_only.empty}") # True を返す
print("-" * 30)
# 3. データが含まれるDataFrame
df_full = pd.DataFrame({'A': [1, 2], 'B': [3, 4]})
print("データが含まれるDataFrame:")
print(df_full)
print(f"df_full.empty: {df_full.empty}") # False を返す
print("-" * 30)
# 4. 全てNaNのDataFrame
df_nan = pd.DataFrame({'A': [np.nan], 'B': [np.nan]})
print("全てNaNのDataFrame:")
print(df_nan)
print(f"df_nan.empty: {df_nan.empty}") # False を返す(NaNもデータとみなされるため)
print("-" * 30)
# 5. 全てNaNのDataFrameからNaNを削除した場合
df_nan_dropped = df_nan.dropna()
print("全てNaNのDataFrameからNaNを削除した場合:")
print(df_nan_dropped)
print(f"df_nan_dropped.empty: {df_nan_dropped.empty}") # True を返す
print("-" * 30)
Pythonでは、空のリスト([]
)や辞書({}
)などは bool()
で評価すると False
となります。しかし、PandasのDataFrameでは、パフォーマンスや意図の明確化のため、bool(DataFrame)
は ValueError
を発生させます。
DataFrameが空であるかどうかをチェックする場合は、必ず df.empty
属性を使用する必要があります。
df_empty = pd.DataFrame()
# if df_empty: # これはエラーになる
# print("Empty!")
if df_empty.empty:
print("DataFrameは空です。")
bool(df) を使って空判定しようとする
エラーの状況
Pythonのリストや辞書のように、DataFrameを直接 if df:
のようにブール値として評価しようとすると、ValueError
が発生します。
import pandas as pd
df = pd.DataFrame()
# if df: # これを実行すると ValueError: The truth value of a DataFrame is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().
# print("DataFrame is not empty")
理由
Pandas DataFrameは、単一の明確な真偽値を持つようには設計されていません。複数の要素が含まれるため、例えば「すべての要素がTrueならTrue」なのか、「一つでもTrueがあればTrue」なのかなど、その評価が曖昧になるためです。このため、Pandasは明示的な empty
属性の使用を強制します。
トラブルシューティング
常に df.empty
を使用してDataFrameが空かどうかをチェックしてください。
df = pd.DataFrame()
if df.empty:
print("DataFrameは空です。")
else:
print("DataFrameは空ではありません。")
NaN (Not a Number) のみが含まれるDataFrameを「空」と誤解する
エラーの状況
DataFrameにデータは入っているものの、そのすべてが NaN
である場合に、df.empty
が False
を返すため、「空ではない」と判断され、期待する処理が行われないことがあります。
import pandas as pd
import numpy as np
df_nan = pd.DataFrame({'A': [np.nan], 'B': [np.nan]})
print(df_nan)
print(f"df_nan.empty: {df_nan.empty}") # False
# df_nan.empty が True を返すことを期待していたが、実際は False
理由
NaN
はPandasにおいて「欠損値」であり、「データが存在しない」こととは異なります。DataFrameのサイズ(行数と列数)がゼロでない限り、empty
属性は False
を返します。
トラブルシューティング
DataFrameからすべての NaN
値を削除した後で空かどうかをチェックすることで、意図した通りの「実質的に空」であるかを判定できます。
df_nan = pd.DataFrame({'A': [np.nan], 'B': [np.nan]})
df_nan_dropped = df_nan.dropna(how='all') # 全てのNaNの行を削除
if df_nan_dropped.empty:
print("NaNのみの行を削除すると、DataFrameは空になります。")
else:
print("NaNのみの行を削除しても、DataFrameは空ではありません。")
# または、特定の列に有効な値があるかどうかをチェックする
if df_nan['A'].dropna().empty and df_nan['B'].dropna().empty:
print("すべての列がNaNのみで構成されています。")
条件によってDataFrameが空になる可能性がある処理の後のハンドリング不足
エラーの状況
フィルタリング、結合 (merge/join)、グループ化 (groupby) などの操作を行った結果、DataFrameが空になる可能性があるにもかかわらず、その後の処理で空のDataFrameを前提としないコードを書いてしまうと、KeyError
や AttributeError
などが発生することがあります。
import pandas as pd
df = pd.DataFrame({'A': [1, 2, 3], 'B': ['x', 'y', 'z']})
# 存在しない条件でフィルタリング
filtered_df = df[df['A'] > 100]
print(f"filtered_df:\n{filtered_df}")
print(f"filtered_df.empty: {filtered_df.empty}") # True
# 空のDataFrameに対して列にアクセスしようとする(一般的なエラー)
# print(filtered_df['B'].iloc[0]) # IndexError: single positional indexer is out-of-bounds
# print(filtered_df.loc[0, 'B']) # KeyError: 0
理由
DataFrameが空の場合、行も列も存在しないため、インデックスや列名を使って要素にアクセスしようとするとエラーになります。
トラブルシューティング
DataFrameに対して何らかの操作を行う前に、または操作後に、empty
属性を使ってDataFrameが空でないことを確認してから、その後の処理に進むようにします。
df = pd.DataFrame({'A': [1, 2, 3], 'B': ['x', 'y', 'z']})
filtered_df = df[df['A'] > 100]
if not filtered_df.empty:
print("フィルタリングされたDataFrameにデータがあります:")
print(filtered_df)
# ここにデータがある場合の処理
else:
print("フィルタリングされたDataFrameは空です。")
# ここにデータがない場合の処理 (例: ログ出力、代替処理)
# 関数内でDataFrameを返す場合も同様
def process_data(df_input):
processed_df = df_input[df_input['value'] > 10]
if processed_df.empty:
print("処理結果のDataFrameは空です。")
return None # または空のDataFrameを返す
else:
print("処理結果のDataFrame:")
print(processed_df)
return processed_df
df_test = pd.DataFrame({'value': [5, 8, 12]})
result_df = process_data(df_test)
if result_df is not None:
# result_df を使った処理
pass
df_empty_test = pd.DataFrame({'value': [1, 2, 3]})
result_empty_df = process_data(df_empty_test)
エラーの状況
pd.read_csv()
や pd.read_excel()
などで、ファイル自体が空、またはヘッダー行しかない場合、pandas.errors.EmptyDataError
が発生することがあります。このエラーは df.empty
をチェックする前に発生します。
# 仮の空ファイルを作成
with open("empty_file.csv", "w") as f:
f.write("") # またはヘッダーのみ: f.write("col1,col2\n")
try:
df_from_file = pd.read_csv("empty_file.csv")
print(f"df_from_file.empty: {df_from_file.empty}")
except pd.errors.EmptyDataError as e:
print(f"ファイルが空のためエラーが発生しました: {e}")
理由
EmptyDataError
は、Pandasがデータを読み込もうとしたが、読み込むべきデータが見つからなかった場合に発生する例外です。これは、DataFrame.empty
が評価されるよりも前の、データの読み込みフェーズで起こります。
トラブルシューティング
ファイルからデータを読み込む際には、try-except
ブロックを使用して pandas.errors.EmptyDataError
を捕捉し、適切にハンドリングします。
import pandas as pd
import numpy as np
import os
file_path = "data.csv"
# テスト用のファイルを作成 (データあり)
with open(file_path, "w") as f:
f.write("col1,col2\n1,A\n2,B\n")
try:
df = pd.read_csv(file_path)
if df.empty:
print(f"ファイル '{file_path}' から読み込んだDataFrameは空です。")
else:
print(f"ファイル '{file_path}' からデータを読み込みました:")
print(df)
except pd.errors.EmptyDataError:
print(f"ファイル '{file_path}' は空か、またはヘッダーのみです。")
except FileNotFoundError:
print(f"ファイル '{file_path}' が見つかりません。")
except Exception as e:
print(f"データの読み込み中に予期せぬエラーが発生しました: {e}")
finally:
# テスト用ファイルの削除
if os.path.exists(file_path):
os.remove(file_path)
# テスト用のファイルを作成 (空)
file_path_empty = "empty_data.csv"
with open(file_path_empty, "w") as f:
pass # 空ファイル
try:
df_empty_file = pd.read_csv(file_path_empty)
if df_empty_file.empty:
print(f"ファイル '{file_path_empty}' から読み込んだDataFrameは空です。")
else:
print(f"ファイル '{file_path_empty}' からデータを読み込みました:")
print(df_empty_file)
except pd.errors.EmptyDataError:
print(f"ファイル '{file_path_empty}' は空か、またはヘッダーのみです。")
except FileNotFoundError:
print(f"ファイル '{file_path_file}' が見つかりません。")
except Exception as e:
print(f"データの読み込み中に予期せぬエラーが発生しました: {e}")
finally:
# テスト用ファイルの削除
if os.path.exists(file_path_empty):
os.remove(file_path_empty)
pandas.DataFrame.empty
のプログラミング例
pandas.DataFrame.empty
は、DataFrameがデータを含んでいるかどうかを効率的にチェックするための重要な属性です。ここでは、一般的なシナリオにおける使用例をいくつか紹介します。
import pandas as pd
import numpy as np
print("--- 1. 基本的な空のDataFrameのチェック ---")
# 完全な空のDataFrame
df_empty_full = pd.DataFrame()
print(f"df_empty_full:\n{df_empty_full}")
print(f"df_empty_full.empty: {df_empty_full.empty}") # True
print("\n--- 2. 列のみ定義され、行がないDataFrameのチェック ---")
# 列は定義されているが、行がないDataFrame
df_cols_only = pd.DataFrame(columns=['A', 'B', 'C'])
print(f"df_cols_only:\n{df_cols_only}")
print(f"df_cols_only.empty: {df_cols_only.empty}") # True
print("\n--- 3. データを含むDataFrameのチェック ---")
# データを含むDataFrame
df_data = pd.DataFrame({'col1': [1, 2], 'col2': ['X', 'Y']})
print(f"df_data:\n{df_data}")
print(f"df_data.empty: {df_data.empty}") # False
print("\n--- 4. すべてNaNのDataFrameのチェック ---")
# 全ての要素がNaNのDataFrame
df_all_nan = pd.DataFrame({'col1': [np.nan], 'col2': [np.nan]})
print(f"df_all_nan:\n{df_all_nan}")
print(f"df_all_nan.empty: {df_all_nan.empty}") # False (NaNもデータとみなされるため)
# NaNのみのDataFrameを実質的に空と判断したい場合
df_all_nan_dropped = df_all_nan.dropna(how='all')
print(f"\ndf_all_nan.dropna(how='all'):\n{df_all_nan_dropped}")
print(f"df_all_nan_dropped.empty: {df_all_nan_dropped.empty}") # True
例1: 関数の引数として渡されたDataFrameが空でないか確認する
関数がDataFrameを受け取り、そのDataFrameが空でない場合にのみ特定の処理を実行したい場合によく使われます。
def process_dataframe(df: pd.DataFrame):
"""
DataFrameを受け取り、空でない場合にのみ処理を実行する関数。
"""
if df.empty:
print("警告: 処理するDataFrameが空です。")
return None # または空のDataFrameを返す、エラーを発生させるなど
print("DataFrameを処理中...")
# 例: 特定の列を合計する
if 'value' in df.columns:
total = df['value'].sum()
print(f"合計値: {total}")
return total
else:
print("エラー: 'value' 列が見つかりません。")
return None
print("\n--- 5. 関数内での空チェック ---")
df1 = pd.DataFrame({'value': [10, 20, 30], 'category': ['A', 'B', 'A']})
process_dataframe(df1)
df2 = pd.DataFrame() # 空のDataFrame
process_dataframe(df2)
df3 = pd.DataFrame(columns=['id', 'name']) # 列のみのDataFrame
process_dataframe(df3)
df4 = pd.DataFrame({'other_col': [1, 2]}) # 'value' 列がないDataFrame
process_dataframe(df4)
例2: フィルタリングや結合操作の結果が空になる可能性がある場合
データの前処理や分析において、特定の条件でフィルタリングしたり、複数のDataFrameを結合したりした結果、DataFrameが空になることがあります。その後の処理でエラーを防ぐために empty
を使用します。
print("\n--- 6. フィルタリング後の空チェック ---")
data = {'product': ['A', 'B', 'C', 'D'], 'price': [100, 200, 150, 50]}
df_products = pd.DataFrame(data)
# 条件に合うデータがある場合
expensive_products = df_products[df_products['price'] > 120]
if not expensive_products.empty:
print("高価な商品:")
print(expensive_products)
else:
print("高価な商品は見つかりませんでした。")
# 条件に合うデータがない場合
very_expensive_products = df_products[df_products['price'] > 500]
if not very_expensive_products.empty:
print("非常に高価な商品:")
print(very_expensive_products)
else:
print("非常に高価な商品は見つかりませんでした。")
print("\n--- 7. 結合(merge)後の空チェック ---")
df_left = pd.DataFrame({'id': [1, 2, 3], 'name': ['Alice', 'Bob', 'Charlie']})
df_right = pd.DataFrame({'id': [2, 4], 'score': [85, 90]})
# 共通のIDがある結合
merged_df = pd.merge(df_left, df_right, on='id', how='inner')
if not merged_df.empty:
print("結合結果 (データあり):")
print(merged_df)
else:
print("結合結果は空でした。")
# 共通のIDがない結合
df_right_no_match = pd.DataFrame({'id': [5, 6], 'score': [70, 75]})
merged_no_match_df = pd.merge(df_left, df_right_no_match, on='id', how='inner')
if not merged_no_match_df.empty:
print("結合結果 (データなし、表示されないはず):")
print(merged_no_match_df)
else:
print("結合結果は空でした。")
例3: 外部データソースからの読み込み後
pd.read_csv
などでファイルを読み込む際、ファイルが空だったり、ヘッダー行しか含まれていなかったりする場合があります。この場合、EmptyDataError
が発生するか、空のDataFrameが返される可能性があります。
import os
print("\n--- 8. ファイル読み込み後の空チェックとエラーハンドリング ---")
file_name_data = "temp_data_with_content.csv"
file_name_empty = "temp_empty_file.csv"
file_name_header_only = "temp_header_only.csv"
# テストファイルの作成
with open(file_name_data, 'w') as f:
f.write("A,B\n1,X\n2,Y\n")
with open(file_name_empty, 'w') as f:
pass # 空のファイル
with open(file_name_header_only, 'w') as f:
f.write("C,D\n")
def load_and_check(file_path):
print(f"\nファイル '{file_path}' を読み込み中...")
try:
df = pd.read_csv(file_path)
if df.empty:
print(f"DataFrameは空です。")
else:
print("DataFrameが読み込まれました:")
print(df)
except pd.errors.EmptyDataError:
print(f"エラー: ファイル '{file_path}' はデータを含んでいません(ヘッダーのみの場合も含む)。")
except FileNotFoundError:
print(f"エラー: ファイル '{file_path}' が見つかりません。")
except Exception as e:
print(f"予期せぬエラーが発生しました: {e}")
load_and_check(file_name_data)
load_and_check(file_name_empty)
load_and_check(file_name_header_only) # ヘッダーのみの場合、通常はempty=Trueになる
# テストファイルのクリーンアップ
os.remove(file_name_data)
os.remove(file_name_empty)
os.remove(file_name_header_only)
-
- 意味
DataFrameの行数が0であるかどうかをチェックします。これはdf.empty
と同じ結果を返すことがほとんどですが、厳密にはdf.empty
が列が定義されていても行がなければTrue
を返すのに対し、len(df)
は行数を見るため、ほとんどの場合同じです。 - 利点
Pythonの一般的なオブジェクト(リストなど)の長さをチェックする方法と似ており、直感的に理解しやすい。 - 欠点
df.empty
の方がPandasのDataFrameに特化しており、意図が明確です。また、len(df)
は内部的にdf.__len__
を呼び出すため、df.empty
よりもわずかにオーバーヘッドがある可能性があります(通常は無視できるレベル)。 - コード例
import pandas as pd df_empty = pd.DataFrame() df_data = pd.DataFrame({'A': [1, 2]}) df_cols_only = pd.DataFrame(columns=['X', 'Y']) print(f"df_empty.empty: {df_empty.empty}, len(df_empty): {len(df_empty)}") # True, 0 print(f"df_data.empty: {df_data.empty}, len(df_data): {len(df_data)}") # False, 2 print(f"df_cols_only.empty: {df_cols_only.empty}, len(df_cols_only): {len(df_cols_only)}") # True, 0
- 意味
-
df.dropna(how='all').empty
(すべてのNaNの行を削除後に空であるかどうかのチェック)- 意味
DataFrameからすべての値がNaNである行を削除した結果、DataFrameが空になるかどうかをチェックします。これは、データが実質的に存在しない(つまり、残っている行には有効なデータがない)状態を「空」と見なしたい場合に非常に便利です。 - 利点
実際に意味のあるデータがDataFrame内に存在するかどうかを判断するのに役立ちます。 - 欠点
DataFrameのコピーを作成し、dropna()
操作を実行するため、計算コストがかかります。元のDataFrameは変更されません。 - コード例
import pandas as pd import numpy as np df_empty = pd.DataFrame() df_data = pd.DataFrame({'A': [1, 2]}) df_all_nan_rows = pd.DataFrame({'A': [np.nan, np.nan], 'B': [np.nan, np.nan]}) df_mixed_nan = pd.DataFrame({'A': [1, np.nan], 'B': [np.nan, 2]}) df_some_nan_rows = pd.DataFrame({'A': [np.nan, 1], 'B': [np.nan, 2]}) df_row_all_nan = pd.DataFrame({'A': [1, np.nan], 'B': [2, np.nan]}) print(f"df_empty.dropna(how='all').empty: {df_empty.dropna(how='all').empty}") # True print(f"df_data.dropna(how='all').empty: {df_data.dropna(how='all').empty}") # False print(f"df_all_nan_rows.dropna(how='all').empty: {df_all_nan_rows.dropna(how='all').empty}") # True print(f"df_mixed_nan.dropna(how='all').empty: {df_mixed_nan.dropna(how='all').empty}") # False (有効なデータを持つ行があるため) print(f"df_some_nan_rows.dropna(how='all').empty: {df_some_nan_rows.dropna(how='all').empty}") # False print(f"df_row_all_nan.dropna(how='all').empty: {df_row_all_nan.dropna(how='all').empty}") # False
df_row_all_nan
の例では、dropna(how='all')
を適用すると2行目が削除されますが、1行目は残るためempty
はFalse
になります。
- 意味
-
df.size == 0
(要素の総数によるチェック)- 意味
DataFrame内の要素の総数(行数 × 列数)が0であるかどうかをチェックします。これはdf.empty
と同じ結果を返します。 - 利点
empty
属性の内部的な実装に近い考え方であり、明示的に要素数を確認できます。 - 欠点
df.empty
がより直接的でPandasの慣習に沿っています。 - コード例
import pandas as pd df_empty = pd.DataFrame() df_data = pd.DataFrame({'A': [1, 2]}) df_cols_only = pd.DataFrame(columns=['X', 'Y']) print(f"df_empty.empty: {df_empty.empty}, df_empty.size == 0: {df_empty.size == 0}") # True, True print(f"df_data.empty: {df_data.empty}, df_data.size == 0: {df_data.size == 0}") # False, False print(f"df_cols_only.empty: {df_cols_only.empty}, df_cols_only.size == 0: {df_cols_only.size == 0}") # True, True
- 意味
代替方法 | 意味合い | df.empty との比較 | ユースケース |
---|---|---|---|
len(df) または df.shape[0] | 行数がゼロか | ほとんどの場合 df.empty と同じ結果。df.empty の方が推奨。 | Pythonの他のコレクションと同じように長さをチェックしたい場合。 |
df.isnull().all().all() | すべての要素がNaNか | df.empty とは異なる概念。NaNのDataFrameは empty=False だがこれは True 。 | データは存在するが行っているが、有効なデータが一切ないかを判断したい場合。 |
df.dropna(how='all').empty | すべてNaNの行を削除した後で空になるか | 実質的なデータ有無のチェック。df.empty より深い意味での「空」。 | 実質的なデータがない状態(NaNのみの行は無視したい)を「空」と見なしたい場合。 |
df.size == 0 | 要素の総数がゼロか | df.empty と同じ結果。df.empty の方が推奨。 | 明示的に要素数をチェックしたい場合。 |
最も推奨されるのは、ほとんどのシナリオで df.empty
を使用することです。 これはPandasが提供する最も意図が明確で効率的な方法だからです。