在 Dask 中,我如何删除在另一列的所有值中不重复的数据?

In Dask, how would I remove data that is not repeated across all values of another column?

我正在尝试查找存在于列值的多个实例中的一组数据。

举个例子,假设我有一个具有以下值的 DataFrame:

+-------------+------------+----------+
| hardware_id | model_name | data_v   |
+-------------+------------+----------+
| a           | 1          | 0.595150 |
+-------------+------------+----------+
| b           | 1          | 0.285757 |
+-------------+------------+----------+
| c           | 1          | 0.278061 |
+-------------+------------+----------+
| d           | 1          | 0.578061 |
+-------------+------------+----------+
| a           | 2          | 0.246565 |
+-------------+------------+----------+
| b           | 2          | 0.942299 |
+-------------+------------+----------+
| c           | 2          | 0.658126 |
+-------------+------------+----------+
| a           | 3          | 0.160283 |
+-------------+------------+----------+
| b           | 3          | 0.180021 |
+-------------+------------+----------+
| c           | 3          | 0.093628 |
+-------------+------------+----------+
| d           | 3          | 0.033813 |
+-------------+------------+----------+

我想要得到的是一个包含所有元素的 DataFrame 除了 包含 hardware_id of d 的行,因为它们确实每个 model_name.

至少不会出现一次

我正在使用 Dask,因为我的原始数据大小约为 7 GB,但如果我需要降低到 Pandas 这也是可行的。我很高兴听到任何建议。

我尝试根据 model_name 属性将数据帧拆分为单独的数据帧,然后 运行 一个循环:

models = ['1','1','1','2','2','2','3','3','3','3']
import dask.dataframe as dd

frame_1 = dd.DataFrame( {'hardware_id':['a','b','c','a','b','c','a','b','c','d'], 'model_name':mn,'data_v':np.random.rand(len(mn))} )
model_splits = []
for i in range(1,4):
     model_splits.append(frame_1[frame_1['model_name'.eq(str(i))]])

aggregate_list = []

while len(model_splits) > 0:
     data = aggregate_list.pop()
     for other_models in aggregate_list:
          data = data[data.hardware_id.isin(other_models.hardware_id.to__bag())]
     aggregate_list.append(data)

final_data = dd.concat(aggregate_list)

但是,这太低效了,我不确定我的逻辑是否合理。

关于如何实现这一点有什么建议吗?

谢谢!

实现此目的的一种方法是将其视为 groupby 聚合问题。

Pandas

首先,我们设置数据:

import pandas as pd
import numpy as np

np.random.seed(12)

models = ['1','1','1','2','2','2','3','3','3','3']

df = pd.DataFrame(
    {'hardware_id':['a','b','c','a','b','c','a','b','c','d'],
     'model_name': models,
     'data_v': np.random.rand(len(models))
    }
)

然后,收集 model_name 列的唯一值。

unique_model_names = df.model_name.unique()
unique_model_names
array(['1', '2', '3'], dtype=object)

接下来,我们将一次性完成几个相关步骤。我们的目标是找出哪些 hardware_idsmodel_names 的整个唯一集合同时出现。首先,我们可以进行 groupby 聚合以获得每个 hardware_id 的唯一 model_names。这是一个 returns 列表,但我们希望将其作为元组以提高效率,以便在下一步中使用。此时,每个硬件 ID 都与其唯一模型的元组相关联。接下来,我们使用 isin 检查该元组是否与我们的唯一模型名称完全匹配。如果不是,我们知道条件应该是假的(正是我们得到的)。

agged = df.groupby("hardware_id", as_index=False).agg({"model_name": "unique"})
agged["model_name"] = agged["model_name"].map(tuple)
agged["all_present_mask"] = agged["model_name"].isin([tuple(unique_model_names)])
agged
    hardware_id model_name  all_present_mask
0   a   (1, 2, 3)   True
1   b   (1, 2, 3)   True
2   c   (1, 2, 3)   True
3   d   (3,)    False

最后,我们可以使用它来获取我们的“有效”硬件 ID 列表,然后过滤我们的初始数据帧。

relevant_ids = agged.loc[
    agged.all_present_mask
].hardware_id
​
result = df.loc[
    df.hardware_id.isin(relevant_ids)
]
result
hardware_id model_name  data_v
0   a   1   0.154163
1   b   1   0.740050
2   c   1   0.263315
3   a   2   0.533739
4   b   2   0.014575
5   c   2   0.918747
6   a   3   0.900715
7   b   3   0.033421
8   c   3   0.956949

达斯克

我们基本上可以做同样的事情,但我们需要在调用计算时聪明一些。

import dask.dataframe as dd
​
ddf = dd.from_pandas(df, 2)
unique_model_names = ddf.model_name.unique()
​
agged = ddf.groupby("hardware_id").model_name.unique().reset_index()
agged["model_name"] = agged["model_name"].map(tuple)
agged["all_present_mask"] = agged["model_name"].isin([tuple(unique_model_names)])
​
relevant_ids = agged.loc[
    agged.all_present_mask
].hardware_id
​
result = ddf.loc[
    ddf.hardware_id.isin(relevant_ids.compute()) # cant pass a dask Series to `ddf.isin`
]
result.compute()
hardware_id model_name  data_v
0   a   1   0.154163
1   b   1   0.740050
2   c   1   0.263315
3   a   2   0.533739
4   b   2   0.014575
5   c   2   0.918747
6   a   3   0.900715
7   b   3   0.033421
8   c   3   0.956949

请注意,如果您有可用内存以避免一些冗余计算,您可能希望保留 agged_dfrelevant_ids