Python Dask - 2 个 DataFrame 的垂直连接

Python Dask - vertical concatenation of 2 DataFrames

我正在尝试垂直连接两个 Dask DataFrame

我有以下 Dask DataFrame:

d = [
    ['A','B','C','D','E','F'],
    [1, 4, 8, 1, 3, 5],
    [6, 6, 2, 2, 0, 0],
    [9, 4, 5, 0, 6, 35],
    [0, 1, 7, 10, 9, 4],
    [0, 7, 2, 6, 1, 2]
    ]
df = pd.DataFrame(d[1:], columns=d[0])
ddf = dd.from_pandas(df, npartitions=5)

这里的数据是 Pandas DataFrame

          A         B      C      D      E      F
0         1         4      8      1      3      5
1         6         6      2      2      0      0
2         9         4      5      0      6     35
3         0         1      7     10      9      4
4         0         7      2      6      1      2

这是 Dask DataFrame

Dask DataFrame Structure:
                   A      B      C      D      E      F
npartitions=4                                          
0              int64  int64  int64  int64  int64  int64
1                ...    ...    ...    ...    ...    ...
2                ...    ...    ...    ...    ...    ...
3                ...    ...    ...    ...    ...    ...
4                ...    ...    ...    ...    ...    ...
Dask Name: from_pandas, 4 tasks

我正在尝试垂直连接 2 个 Dask DataFrame:

ddf_i = ddf + 11.5
dd.concat([ddf,ddf_i],axis=0)

但是我得到这个错误:

Traceback (most recent call last):
      ...
      File "...", line 572, in concat
        raise ValueError('All inputs have known divisions which cannot '
    ValueError: All inputs have known divisions which cannot be concatenated
    in order. Specify interleave_partitions=True to ignore order

但是,如果我尝试:

dd.concat([ddf,ddf_i],axis=0,interleave_partitions=True)

然后它似乎可以正常工作。将此设置为 True 是否有问题(就性能 - 速度而言)?或者还有另一种垂直连接 Dask DataFrames 的方法吗?

如果你检查数据帧的分区 ddf.divisions,你会发现,假设一个分区,它有索引的边缘:(0, 4)。这对 dask 很有用,因为它知道您何时对数据执行某些操作,而不是使用不包含所需索引值的分区。这也是为什么当索引适合作业时一些 dask 操作要快得多的原因。

连接时,第二个数据帧与第一个数据帧具有相同的索引。如果索引的值在两个分区中具有不同的范围,则串联将在没有交错的情况下工作。

mdurant 的答案是正确的,这个答案使用 Dask v2021.08.1 详细说明了 MCVE 代码片段。例子更容易理解除法和交错。

垂直连接数据帧

创建两个 DataFrame,连接它们,然后查看结果。

df = pd.DataFrame(
    {"nums": [1, 2, 3, 4, 5, 6], "letters": ["a", "b", "c", "d", "e", "f"]}
)
ddf1 = dd.from_pandas(df, npartitions=2)

df = pd.DataFrame({"nums": [88, 99], "letters": ["xx", "yy"]})
ddf2 = dd.from_pandas(df, npartitions=1)

ddf3 = dd.concat([ddf1, ddf2])

print(ddf3.compute())

   nums letters
0     1       a
1     2       b
2     3       c
3     4       d
4     5       e
5     6       f
0    88      xx
1    99      yy

垂直连接时分割元数据

创建两个DataFrame,将它们拼接起来,说明有时这个操作会导致分区元数据丢失。

def print_partitions(ddf):
    for i in range(ddf.npartitions):
        print(ddf.partitions[i].compute())

df = pd.DataFrame(
    {"nums": [1, 2, 3, 4, 5, 6], "letters": ["a", "b", "c", "d", "e", "f"]}
)
ddf1 = dd.from_pandas(df, npartitions=2)

ddf1.divisions # (0, 3, 5)

df = pd.DataFrame({"nums": [88, 99], "letters": ["xx", "yy"]})
ddf2 = dd.from_pandas(df, npartitions=1)

ddf2.divisions # (0, 1)

ddf3 = dd.concat([ddf1, ddf2])

ddf3.divisions # (None, None, None, None)

设置 interleave_partitions=True 以避免丢失分区元数据。

ddf3_interleave = dd.concat([ddf1, ddf2], interleave_partitions=True)

ddf3_interleave.divisions # (0, 1, 3, 5)

不需要交织时

创建两个没有重叠分区的DataFrame,连接它们,并确认分区元数据没有丢失:

df = pd.DataFrame(
    {"nums": [1, 2, 3, 4], "letters": ["a", "b", "c", "d"], "some_index": [4, 5, 6, 7]}
)
ddf1 = dd.from_pandas(df, npartitions=2)

ddf1 = ddf1.set_index("some_index")

df = pd.DataFrame({"nums": [88, 99], "letters": ["xx", "yy"], "some_index": [10, 20]})
ddf2 = dd.from_pandas(df, npartitions=1)

ddf2 = ddf2.set_index("some_index")

ddf3 = dd.concat([ddf1, ddf2])

ddf3.divisions # (4, 6, 10, 20)

我写了一篇博客 post 来更详细地解释这一点。如果您想要 link.

,请告诉我