(圧縮された)JSON形式の列が多数ある大きなデータセットがあります。その後の処理のために寄木細工に変換しようとしています。一部の列にはネスト構造があります。とりあえず、この構造を無視して、それらの列を(JSON)文字列として書き出します。
だから私が特定した列について私はやっています:
df[column] = df[column].astype(str)
ただし、ネストされている列とネストされていない列はわかりません。寄木細工で書くと、次のメッセージが表示されます。
<stack trace redacted>
File "pyarrow/_parquet.pyx", line 1375, in pyarrow._parquet.ParquetWriter.write_table
File "pyarrow/error.pxi", line 78, in pyarrow.lib.check_status
pyarrow.lib.ArrowInvalid: Nested column branch had multiple children: struct<coordinates: list<item: double>, type: string>
これは、列の1つをネストされたオブジェクトから文字列に変換できなかったことを示しています。しかし、どの列に責任がありますか?どうすればわかりますか?
pandasデータフレームの.dtypes
を印刷すると、文字列とネストされた値を区別できません。どちらもobject
と表示されるためです。
編集:エラーは構造体の詳細を表示することにより、ネストされた列に関するヒントを提供しますが、これはデバッグに非常に時間がかかります。また、最初のエラーのみを出力します。ネストされた列が複数ある場合、これは非常に煩わしくなります。
Pysparkとストリーミングデータセットを操作するときに同様の問題が発生しました。ネストされた列とネストされなかった列があります。
データフレームが次のようになる場合を考えます:
df = pd.DataFrame({'A' : [{1 : [1,5], 2 : [15,25], 3 : ['A','B']}],
'B' : [[[15,25,61],[44,22,87],['A','B',44]]],
'C' : [((15,25,87),(22,91))],
'D' : 15,
'E' : 'A'
})
print(df)
A \
0 {1: [1, 5], 2: [15, 25], 3: ['A', 'B']}
B C D E
0 [[15, 25, 61], [44, 22, 87], [A, B, 44]] ((15, 25, 87), (22, 91)) 15 A
データフレームをスタックし、apply
をtype
とともに使用して、各列のタイプを取得し、辞書に渡すことができます。
df.head(1).stack().apply(type).reset_index(0,drop=True).to_dict()
out:
{'A': dict, 'B': list, 'C': Tuple, 'D': int, 'E': str}
これにより、関数を使用して、ネストされた列とネストされていない列のタプルを返すことができます。
def find_types(dataframe):
col_dict = dataframe.head(1).stack().apply(type).reset_index(0,drop=True).to_dict()
unnested_columns = [k for (k,v) in col_dict.items() if v not in (dict,set,list,Tuple)]
nested_columns = list(set(col_dict.keys()) - set(unnested_columns))
return nested_columns,unnested_columns
nested,unested = find_types(df)
df[unested]
D E
0 15 A
print(df[nested])
C A \
0 ((15, 25, 87), (22, 91)) {1: [1, 5], 2: [15, 25], 3: ['A', 'B']}
B
0 [[15, 25, 61], [44, 22, 87], [A, B, 44]]
どの列が原因であるかを調べたいだけの場合は、一度に1つの列を書き込み、失敗した列を格納するループを作成します...
bad_cols = []
for i in range(df.shape[1]):
try:
df.iloc[:, [i]].to_parquet(...)
except KeyboardInterrupt:
raise
except Exception: # you may want to catch ArrowInvalid exceptions instead
bad_cols.append(i)
print(bad_cols)
infer_dtype()
in pandas=のような一般的なユーティリティ関数を使用すると、列がネストされているかどうかを判別できます。
from pandas.api.types import infer_dtype
for col in df.columns:
if infer_dtype(df[col]) == 'mixed' :
# ‘mixed’ is the catchall for anything that is not otherwise specialized
df[col] = df[col].astype('str')
特定のデータ型をターゲットにしている場合は、 Dtype Introspection を参照してください。