次のデータフレームがあるとしましょう(整数の列と整数のリストの列)...
ID Found_IDs
0 12345 [15443, 15533, 3433]
1 15533 [2234, 16608, 12002, 7654]
2 6789 [43322, 876544, 36789]
また、IDの個別のリスト...
bad_ids = [15533, 876544, 36789, 11111]
それを踏まえて、df['ID']
列とインデックスを無視して、bad_ids
リストのIDがdf['Found_IDs']
列に記載されているかどうかを確認します。私がこれまでに持っているコードは:
df['bad_id'] = [c in l for c, l in Zip(bad_ids, df['Found_IDs'])]
これは機能しますが、bad_ids
リストがデータフレームよりも長く、実際のデータセットのbad_ids
リストがデータフレームよりもはるかに短い場合のみです。 bad_ids
リストを2つの要素のみに設定すると...
bad_ids = [15533, 876544]
私は非常に人気のあるエラーを受け取ります(同じエラーで多くの質問を読みました)...
ValueError: Length of values does not match length of index
リストをシリーズに変換してみました(エラーは変わりません)。理解の行を実行する前に、新しい列を追加してすべての値をFalse
に設定することも試みました(ここでもエラーの変更はありません)。
2つの質問:
df['bad_id']
列に書き込むコードを取得するにはどうすればよいですか(True/Falseよりも便利です)?bad_ids = [15533, 876544]
の予想される出力:
ID Found_IDs bad_id
0 12345 [15443, 15533, 3433] True
1 15533 [2234, 16608, 12002, 7654] False
2 6789 [43322, 876544, 36789] True
bad_ids = [15533, 876544]
の理想的な出力(IDは新しい列に書き込まれます):
ID Found_IDs bad_id
0 12345 [15443, 15533, 3433] 15533
1 15533 [2234, 16608, 12002, 7654] False
2 6789 [43322, 876544, 36789] 876544
コード:
import pandas as pd
result_list = [[12345,[15443,15533,3433]],
[15533,[2234,16608,12002,7654]],
[6789,[43322,876544,36789]]]
df = pd.DataFrame(result_list,columns=['ID','Found_IDs'])
# works if list has four elements
# bad_ids = [15533, 876544, 36789, 11111]
# fails if list has two elements (less elements than the dataframe)
# ValueError: Length of values does not match length of index
bad_ids = [15533, 876544]
# coverting to Series doesn't change things
# bad_ids = pd.Series(bad_ids)
# print(type(bad_ids))
# setting up a new column of false values doesn't change things
# df['bad_id'] = False
print(df)
df['bad_id'] = [c in l for c, l in Zip(bad_ids, df['Found_IDs'])]
print(bad_ids)
print(df)
Np.anyを適用して使用できます。
df['bad_id'] = df['Found_IDs'].apply(lambda x: np.any([c in x for c in bad_ids]))
このbad_idを取得したい場合は、Found_IDにbad_idが存在する場合、これはブール値を返します。
df['bad_id'] = df['Found_IDs'].apply(lambda x: [*filter(lambda x: c in x, bad_ids)])
これはfound_idsにあるbad_idsのリストを返します。0がある場合は[]を返します
merge
とconcat
を使用してインデックスをグループ化し、すべての一致を返します。
bad_ids = [15533, 876544, 36789, 11111]
df2 = pd.concat(
[
df,
pd.merge(
df["Found_IDs"].explode().reset_index(),
pd.Series(bad_ids, name="bad_ids"),
left_on="Found_IDs",
right_on="bad_ids",
how="inner",
)
.groupby("index")
.agg(bad_ids=("bad_ids", list)),
],
axis=1,
).fillna(False)
print(df2)
ID Found_IDs bad_ids
0 12345 [15443, 15533, 3433] [15533]
1 15533 [2234, 16608, 12002, 7654] False
2 6789 [43322, 876544, 36789] [876544, 36789]
分解およびグループ化集約を使用する
s = df['Found_IDs'].explode()
df['bad_ids'] = s.isin(bad_ids).groupby(s.index).any()
ために bad_ids = [15533, 876544]
>>> df
ID Found_IDs bad_ids
0 12345 [15443, 15533, 3433] True
1 15533 [2234, 16608, 12002, 7654] False
2 6789 [43322, 876544, 36789] True
[〜#〜]または[〜#〜]
一致する値を取得するため
s = df['Found_IDs'].explode()
s.where(s.isin(bad_ids)).groupby(s.index).agg(lambda x: list(x.dropna()))
ために bad_ids = [15533, 876544]
ID Found_IDs bad_ids
0 12345 [15443, 15533, 3433] [15533]
1 15533 [2234, 16608, 12002, 7654] []
2 6789 [43322, 876544, 36789] [876544]