连接两个Pandas数据帧,从较小的数据帧中采样



我有两个数据帧,如下所示:

import pandas as pd
import io
train_data="""input_example,user_id
example0.npy, jane
example1.npy, bob
example4.npy, alice
example5.npy, jane
example3.npy, bob
example2.npy, bob
"""
user_data="""user_data,user_id
data_jane0.npy, jane
data_jane1.npy, jane
data_bob0.npy, bob
data_bob1.npy, bob
data_alice0.npy, alice
data_alice1.npy, alice
data_alice2.npy, alice
"""
train_df = pd.read_csv(io.StringIO(train_data), sep=",")
user_df = pd.read_csv(io.StringIO(user_data), sep=",")

假设train_df表有数千个条目长,即有1000个唯一的"1";示例N.npy";文件。我想知道是否有一种简单的方法可以合并train_dfuser_df表,其中联接表的每一行都与关键字user_id匹配,但都是从user_df进行子采样的。

下面是一个结果数据帧的例子(我试图进行统一采样,所以理论上,有无限可能的结果数据帧(:

>>> result_df
input_example        user_data   user_id
0    example0.npy   data_jane0.npy      jane
1    example1.npy    data_bob1.npy       bob
2    example4.npy  data_alice0.npy     alice
3    example5.npy   data_jane1.npy      jane
4    example3.npy    data_bob0.npy       bob
5    example2.npy    data_bob0.npy       bob

也就是说,user_data列填充有基于对应的user_id的文件名的随机选择。

我知道可以使用一些基于多行循环查询的方法来写这篇文章,但也许有一种更快的方法可以使用内置的Pandas函数,例如";样品"合并"加入";,或";组合";。

您可以在user_df中按组采样,然后将其与train_df连接。例如

# this samples by fraction so each data is equally likely 
user_df = user_df.groupby("user_id").sample(frac=0.5, replace=True) 
user_data           user_id
6   data_alice2.npy     alice
4   data_alice0.npy     alice
3   data_bob1.npy       bob
0   data_jane0.npy      jane

# this will sample 2 samples per group
user_df = user_df.groupby("user_id").sample(n=2, replace=True) 
user_data           user_id
6   data_alice2.npy     alice
4   data_alice0.npy     alice
2   data_bob0.npy       bob
2   data_bob0.npy       bob
0   data_jane0.npy      jane
1   data_jane1.npy      jane

加入

pd.merge(train_df, user_df)

我不知道是否可以在不首先合并两者的情况下与样本合并。这不包括多行循环:

merged = train_df.merge(user_df, on="user_id", how="left").
groupby("input_example", as_index=False).
apply(lambda x: x.sample(1)).
reset_index(drop=True)
  1. 将两者合并在一起;user_id";,只取左边出现的
  2. 分组依据";input_example";,假设这些都是唯一的(其他可以在train_df的两列上分组(
  3. 取一个1号的样品
  4. 重置索引

合并后的第二次采样意味着具有相同user_id的行不一定相同(但首先对user_df进行采样会导致输出数据帧中的所有行具有相同的user_id(。

我想我自己找到了一个解决方案,这是一个单行线,但从概念上讲,它与@Rawson建议的相同。首先,我做了一个左合并,结果是一个有很多重复项的表。然后我打乱所有的行,使其具有随机性。最后,我删除了重复项。如果我加上";sort_ index";,生成的表将具有与原始表相同的顺序。

我可以使用random_statekwarg来切换使用哪个user_data文件。请参阅此处:

>>> train_df.merge(user_df, on='user_id', how='left').sample(frac=1, random_state=0).drop_duplicates('input_example').sort_index()
input_example user_id        user_data
1   example0.npy    jane   data_jane1.npy
2   example1.npy     bob    data_bob0.npy
6   example4.npy   alice  data_alice2.npy
8   example5.npy    jane   data_jane1.npy
10  example3.npy     bob    data_bob1.npy
11  example2.npy     bob    data_bob0.npy
>>> train_df.merge(user_df, on='user_id', how='left').sample(frac=1, random_state=1).drop_duplicates('input_example').sort_index()
input_example user_id        user_data
1   example0.npy    jane   data_jane1.npy
2   example1.npy     bob    data_bob0.npy
4   example4.npy   alice  data_alice0.npy
7   example5.npy    jane   data_jane0.npy
10  example3.npy     bob    data_bob1.npy
12  example2.npy     bob    data_bob1.npy

最新更新