【问题标题】:Python Dask dataframe separation based on column value基于列值的Python Dask数据框分离
【发布时间】:2019-06-05 07:58:37
【问题描述】:

我是 python dask 的新手(对 pandas 有一点经验)。我有一个大的 Dask 数据框(约 10 到 2000 万行),我必须根据唯一的列值将其分开。

例如,如果我有以下包含 C1 到 Cn 列的数据框(抱歉,不知道如何在 stackoverflow 中制作正确的表格)并且我想为 C2 列的每个唯一值创建子集数据框

Base Dataframe:


|Ind| C1 | C2 |....| Cn |
|-----------------------|
| 1 |val1| AE |....|time|
|-----------------------|
| 2 |val2| FB |....|time|
|-----------------------|
|...|....| .. |....| ...|
|-----------------------|
| n |valn| QK |....|time|
Subset Dataframes to be created:

Subset 1:

|Ind| C1 | C2 |....| Cn |
|-----------------------|
| 1 |val1| AE |....|time|
|-----------------------|
| 2 |val2| AE |....|time|
|-----------------------|
|...|....| .. |....| ...|
|-----------------------|
| n |valn| AE |....|time|

Subset 2

|Ind| C1 | C2 |....| Cn |
|-----------------------|
| 1 |val1| FB |....|time|
|-----------------------|
| 2 |val2| FB |....|time|
|-----------------------|
|...|....| .. |....| ...|
|-----------------------|
| n |valn| FB |....|time|


and so on.

我目前的方法是获取 C2 的所有唯一值并迭代地过滤每个这些值的基本数据帧。但这需要很长时间。我目前正在研究如何改进这个过程,但如果你们中的任何人能给我一些建议,我将不胜感激。

【问题讨论】:

  • 是否要将子集保存在磁盘上?
  • 不...我稍后必须分别处理不同的数据帧

标签: python dataframe subset data-science dask


【解决方案1】:

在我看来,您可以在pandasdask 中获得与groupby 相同的子集。

import pandas as pd
import dask.dataframe as dd
import numpy as np
import string

N = 5
rndm2 = lambda :"".join(np.random.choice(list(string.ascii_lowercase), 2))
df_sample = pd.DataFrame({"C1":np.arange(N),
                          "C2":[rndm2() for i in range(N)],
                          "C3":np.random.randn(N)})

M = 2
df = pd.concat([df_sample for i in range(M)], ignore_index=True)
df["C4"] =  np.random.randn(N*M)

这里我只是打印print(list(df.groupby("C2"))[0][1]) 来向您展示每个组中的内容:

   C1  C2        C3        C4
3   3  bx  0.668654 -0.237081
8   3  bx  0.668654  0.619883

如果您需要对磁盘进行良好分区,您可以执行以下操作

ddf = dd.from_pandas(df, npartitions=4)
ddf.to_parquet("saved/", partition_on=["C2"])

# You can check that the parquet files
# are in separated folder as
! ls saved/ # If you are on Linux

'C2=iw'  'C2=jl'  'C2=qf'  'C2=wy'  'C2=yr'   _common_metadata

现在,如果您想使用这些组执行一些计算,您可以应用您的函数 funmap_partitions 来处理输出元数据。

df = dd.read_parquet("saved/")
out = df.map_partitions(lambda x: fun(x)).compute() # you should add your output meta

【讨论】:

  • 非常感谢。我会试一试:)
  • 嘿……又是我。您的解决方案是一个好的开始。但我在这里 (stackoverflow.com/a/31364127/2412796) 读到应避免使用 apply() 方法。我现在想将我的索引设置为 C2 列并根据不同的值对数据帧进行分区,然后调用 map_partitions(...) 。问题1:这是个好主意。问题 2:除了获取列的所有唯一条目并调用 df.repartition(divisions=[myUniqueEntriesList]) 之外,您是否知道如何进行此分区
  • 嗨@pichlbaer 我想我迷路了。你介意重新制定吗?我没有在我的回答中使用apply。如果您多次使用相同的数据,最好在磁盘上对其进行很好的分区。使用 set_index 可能与使用 apply 一样昂贵。 dask_performance
  • 嘿...抱歉造成混乱(昨天是漫长的一天)。我必须独立处理数据帧的每个分区......并且一个 dask groupby() 创建一个 DataFrameGroupBy 对象,它只允许应避免的 apply() 方法。现在我想根据唯一的列值重新分区我的数据框,但我不知道这是否是最好的解决方案。我读过 set_index() 很昂贵,我现在只是想找到一个合适的起点
  • 没问题。如果您刚刚开始,我建议您探索不同的解决方案,如 set_index 并保存到磁盘作为答案,看看哪一个最适合您
猜你喜欢
  • 2018-09-07
  • 1970-01-01
  • 2021-09-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-16
  • 2021-04-14
相关资源
最近更新 更多