在 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_ids
与 model_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_df
和 relevant_ids
。
我正在尝试查找存在于列值的多个实例中的一组数据。
举个例子,假设我有一个具有以下值的 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_ids
与 model_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_df
和 relevant_ids
。