df 是一个包含 1200 万行 + 未排序的数据帧。 每行都有一个组 ID。
最终目标是为每个唯一的组 ID 随机选择 1 行,从而填充一个名为 SELECTED 的新列,其中 1 表示已选择 0 表示相反
可能有 5000+ 个唯一的组 ID。 寻求比以下更好,更快的解决方案,潜在的多线程解决方案?
for sec in df['GROUP'].unique():
sz = df.loc[df.GROUP == sec, ['SELECTED']].size
sel = [0]*sz
sel[random.randint(0,sz-1)] = 1
df.loc[df.GROUP == sec, ['SELECTED']] = sel
您可以尝试矢量化版本,如果您有很多类,这可能会加快速度。
import pandas as pd
# get fake data
df = pd.DataFrame(pd.np.random.rand(10))
df['GROUP'] = df[0].astype(str).str[2]
# mark one element of each group as selected
df['selected'] = df.index.isin( # Is current index in a selected list?
df.groupby('GROUP') # Get a GroupBy object.
.apply(pd.Series.sample) # Select one row from each group.
.index.levels[1] # Access index - in this case (group, old_id) pair; select the old_id out of the two.
).astype(pd.np.int) # Convert to ints.
请注意,如果存在重复索引,此操作可能会失败。
我不知道熊猫的数据帧,但是如果您只是将需要的选定设置为一个,然后假设没有该属性意味着未选择,则可以避免更新所有元素。
你也可以做这样的事情:
selected = []
for sec in df['GROUP'].unique():
selected.append(random.choice(sec))
或使用列表推导
selected = [random.choice(sec) for sec in df['GROUP'].unique()]
也许这可以加快速度,因为您不需要允许新内存并 udpate 数据帧中的所有元素。
如果你真的想要多线程,看看 concurrent.futures https://docs.python.org/3/library/concurrent.futures.html