8

パンダで一連のデータフレームをマージしようとしています。私はdfsdfsのリストとそれに対応するラベルのリストを持っていますlabels.dfからの共通ラベルがリスト内のラベルからサフィックスを取得するように、すべてのdfsを1つのdfにマージしたいと考えていlabelsます。すなわち:

def mymerge(dfs, labels):
  labels_dict = dict([(d, l) for d, l in zip(dfs, labels)])
  merged_df = reduce(lambda x, y:
                     pandas.merge(x, y, 
                                  suffixes=[labels_dict[x], labels_dict[y]]),
                     dfs)
  return merged_df

これを試すと、次のエラーが表示されます。

pandas.tools.merge.MergeError: Combinatorial explosion! (boom)

各マージで最大でも列数 N だけ増加する一連のマージを作成しようとしています。ここで、N はリスト内の「次の」df の列数です。最終的な DF には、すべての df 列を合計した数の列が含まれている必要があるため、組み合わせではなく、加算的に成長します。

私が探している動作は次のとおりです。指定された(たとえば、によって指定されたon=)またはdfsがインデックス付けされた列名でdfsに参加します。一般的でない列名を結合します (外部結合のように)。列が複数の dfs に表示される場合は、必要に応じて上書きします。ドキュメントをさらに見ると、updateこれを行うための最良の方法のように思えます。試しjoin='outer'てみると、実装されていないことを示す例外が発生します。

編集

これは、サフィックスを処理しませんが、探しているマージの種類を示しています。

def my_merge(dfs_list, on):
    """ list of dfs, columns to merge on. """
    my_df = dfs_list[0]
    for right_df in dfs_list[1:]:
        # Only put the columns from the right df
        # that are not in the existing combined df (i.e. new)
        # or which are part of the columns to join on
        new_noncommon_cols = [c for c in right_df \
                              if (c not in my_df.columns) or \
                                 (c in on)]
        my_df = pandas.merge(my_df,
                             right_df[new_noncommon_cols],
                             left_index=True,
                             right_index=True,
                             how="outer",
                             on=on)
    return my_df

これは、各 dfs のインデックスでマージが行われることを前提としています。新しい列は外部結合スタイルで追加されますが、共通の (インデックスの一部ではない) 列は、on=キーワードを介して結合で使用されます。

例:

df1 = pandas.DataFrame([{"employee": "bob",
                         "gender": "male",
                         "bob_id1": "a"},
                        {"employee": "john",
                         "gender": "male",
                         "john_id1": "x"}])
df1 = df1.set_index("employee")
df2 = pandas.DataFrame([{"employee": "mary",
                         "gender": "female",
                         "mary_id1": "c"},
                        {"employee": "bob",
                         "gender": "male",
                         "bob_id2": "b"}])
df2 = df2.set_index("employee")
df3 = pandas.DataFrame([{"employee": "mary",
                         "gender": "female",
                         "mary_id2": "d"}])
df3 = df3.set_index("employee")
merged = my_merge([df1, df2, df3], on=["gender"])
print "MERGED: "
print merged

これのひねりは、一般的な列の一連のラベルに基づいて各 df にサフィックスを任意にタグ付けすることですが、それはそれほど重要ではありません。上記のマージ操作は、パンダでよりエレガントに実行できるものですか、それとも組み込みとして既に存在するものですか?

4

2 に答える 2

5

メソッドの出力:

In [29]: merged
Out[29]: 
         bob_id1  gender john_id1 bob_id2 mary_id1 mary_id2
employee                                                   
bob            a    male      NaN       b      NaN      NaN
john         NaN    male        x     NaN      NaN      NaN
mary         NaN  female      NaN     NaN        c        d

パンダが組み込まれたソリューションdf.combine_first

In [28]: reduce(lambda x,y: x.combine_first(y), [df1, df2, df3])
Out[28]: 
         bob_id1 bob_id2  gender john_id1 mary_id1 mary_id2
employee                                                   
bob            a       b    male      NaN      NaN      NaN
john         NaN     NaN    male        x      NaN      NaN
mary         NaN     NaN  female      NaN        c        d

各フレームの列にサフィックスを追加するには、を呼び出す前に列の名前を変更することをお勧めしますcombine_first

一方、pd.concat([df1, df2, df3], keys=['d1', 'd2', 'd3'], axis=1)MultiIndex 列を含むデータフレームを生成する のような操作を検討することもできます。この場合、性別をインデックスの一部にすることを検討するか、その重複を受け入れることをお勧めします。

于 2013-01-11T17:40:00.213 に答える
1

ソースコードから:

max_groups = 1L
for x in group_sizes:
    max_groups *= long(x)

if max_groups > 2**63:  # pragma: no cover
    raise Exception('Combinatorial explosion! (boom)')

そして、同じファイルで

# max groups = largest possible number of distinct groups
left_key, right_key, max_groups = self._get_group_keys()

この線max_groups *= long(x)は、それが相加的ではないため、重要であることを示しています。

于 2013-01-10T21:19:52.977 に答える