如何按列中列表的元素索引数据?

How to index data by elements of lists in columns?

我有以下 DataFrame(后来命名为 df2):

    recipe_id                                        ingredients
0        3332         [11307, 11322, 11632, 11338, 11478, 11438]
1        3333  [11322, 11338, 11632, 11314, 11682, 11478, 108...
2        3334  [11632, 11682, 11338, 11337, 10837, 11435, 113...
3        3335  [11149, 11322, 11532, 11996, 10616, 10837, 113...
4        3336  [11330, 11632, 11422, 11256, 11338, 11314, 114...
5        3812                      [959, 92, 3, 554, 12271, 202]
...

我想创建另一个包含以下列的 DataFrame:['ingredients', "recipe_id1", "recipe_id2", ..., "recipe_idn"],其中 n 是数据库中的食谱总数。我用以下代码片段做到了这一点:

columns = ['ingredient'] + (list(df2['recipe_id'].unique()))
ingredient_df = pd.DataFrame(columns=columns)


在我创建这个 DataFrame(我已经这样做了)并填充它(我遇到的问题)之后,输出应该如下所示:

In [1]:
# Create and populate ingredient_df by some method
columns = ['ingredient'] + (list(df2['recipe_id'].unique()))
ingredient_df = pd.DataFrame(columns=columns)
ingredient_df = populate_df(ingredient_df, df2)
Out [1]:
In [2]:  
ingredient_df
Out[2]:
   ingredient  ... 3332 3333 3334 3335 3336 ...
...
   11322       ...    1    1    0    1    0 ...
...

在上面的示例中,(11322, 3334) 处的值为 0,因为成分 11322 不存在于 ID 为 3334 的配方中。

换句话说,我希望每个成分都有映射 (ingredient, recipe_id) = 1 如果成分存在于该食谱中,否则 0

我已经设法通过遍历所有食谱和所有成分来做到这一点,但这非常慢。我怎样才能使用 Pandas 方法以更健壮和优雅的方式做到这一点(如果这可能的话)?

设置

df = pd.DataFrame(
    dict(
        recipe_id=list('abcde'),
        ingredients=[list('xyz'),
                     list('tuv'),
                     list('ytw'),
                     list('vy'),
                     list('zxs')]
    )
)[['recipe_id', 'ingredients']]

df

  recipe_id ingredients
0         a   [x, y, z]
1         b   [t, u, v]
2         c   [y, t, w]
3         d      [v, y]
4         e   [z, x, s]

方法一

df.set_index('recipe_id').ingredients.apply(pd.value_counts) \
    .fillna(0).astype(int).T.rename_axis('ingredients')

recipe_id    a  b  c  d  e
ingredients               
s            0  0  0  0  1
t            0  1  1  0  0
u            0  1  0  0  0
v            0  1  0  1  0
w            0  0  1  0  0
x            1  0  0  0  1
y            1  0  1  1  0
z            1  0  0  0  1

方法二

idx = np.repeat(df.index.values, df.ingredients.str.len())
df1 = df.drop('ingredients', 1).loc[idx]
df1['ingredients'] = df.ingredients.sum()

df1.groupby('ingredients').recipe_id.apply(pd.value_counts) \
    .unstack(fill_value=0).rename_axis('recipe_id', 1)

recipe_id    a  b  c  d  e
ingredients               
s            0  0  0  0  1
t            0  1  1  0  0
u            0  1  0  0  0
v            0  1  0  1  0
w            0  0  1  0  0
x            1  0  0  0  1
y            1  0  1  1  0
z            1  0  0  0  1