Dask DataFrame - 根据分隔符将多个字符串列同时拆分为多行

问题描述 投票:0回答:1

我有一个大型 Dask DataFrame,看起来像这样:

POS 身份证 参考 ALT 后果 Ensembl_geneid Ensembl_蛋白质ID Ensembl_transcriptid 等等
1 10000 1-10000-A-C A C con11,con12,con13 基因11,.,基因13 prot11,.,prot13 tra11,.,tra13
1 11000 1-11000-A-G A G con21 基因21 prot21 tra21
2 20000 2-20000-T-C T C .,.,.,.,. .,.,.,.,. .,.,.,.,. .,.,.,.,.
等等

所有列均已使用 Dask DataFrame

read_csv(dtypes_mapping)
有意读取为字符串。实际数据基本上是使用 VEP 工具生成的变异注释数据,总共有几百万行和大约 90-100 列(如果有帮助的话)。

每个变体(即 CHROM、POS、ID、REF、ALT)都有一个或多个逗号分隔的值,对应于不同的效果。 “点”是该工具用来表示缺失值的字符串,我稍后会将其替换为正确的

NaN
值。

可能存在部分或完全缺失,但对于每个变体,每个逗号分隔的字符串列中始终有相同数量的位置值(它们是为了匹配)。例如,

  • 所有“11”值都匹配,
  • “con12”与其他列中的缺失值匹配,等等。

我想应用 Dask

Series.str.split(pat=delim, n=-1, expand=False)
和 Dask
DataFrame.explode(column=col_list)
方法将数据转换为长格式,同时保持位置值匹配,如下所示:

POS 身份证 参考 ALT 后果 Ensembl_geneid Ensembl_蛋白质ID Ensembl_transcriptid 等等
1 10000 1-10000-A-C A C con11 基因11 prot11 tra11
1 10000 1-10000-A-C A C con12 . . .
1 10000 1-10000-A-C A C con13 基因13 prot13 tra13
1 11000 1-11000-A-G A G con21 基因21 prot21 tra21
2 20000 2-20000-T-C T C . . . .
2 20000 2-20000-T-C T C . . . .
2 20000 2-20000-T-C T C . . . .
2 20000 2-20000-T-C T C . . . .
2 20000 2-20000-T-C T C . . . .
等等

当我使用测试样本在 Pandas 中尝试整个过程时,我可以看到使用

.iloc[]
type()
,在 Pandas
Series.str.split()
之后,Pandas DataFrame 将各个值识别为
list[str]
。这样就可以让 Pandas
DataFrame.explode()
按预期工作。

但是,我无法在 Dask 中实现同样的功能。 Dask DataFrame 似乎将 Dask

Series.str.split()
之后的各个值视为
str
而不是
list[str]
"['con11', 'con12', 'con13']"
而不是
['con11', 'con12', 'con13']
)。这导致 Dask
DataFrame.explode()
基本上什么都不做。

这就是我一直提到的,但我不确定接受的解决方案是否适用于我的情况:Dask dataframe - 根据分隔符将列拆分为多行

我无法判断我是否遗漏了一些非常明显的东西,或者这是否是 Dask 设计的限制。任何调试帮助将不胜感激!


编辑:对延迟表示歉意@GuillaumeEB,我在上周左右一直无法回到这个特定问题。这是一个基于上面示例的小型再现器:

### python = 3.12.1 (conda-forge)
### numpy = 1.26.3 (conda-forge)
### pandas = 2.1.4 (conda-forge)
### dask = 2023.12.1 (conda-forge)

import pandas as pd
from dask import dataframe as ddf

reqd_cols = ["Consequence", "Ensembl_geneid", "Ensembl_proteinid", "Ensembl_transcriptid"]

### Pandas implementation start, works as intended
df  = pd.DataFrame({
    "CHROM": [1, 1, 2],
    "POS": [10000, 11000, 20000],
    "ID": ["1-10000-A-C", "1-11000-A-G", "2-20000-T-C"],
    "REF": ["A", "A", "T"],
    "ALT": ["C", "G", "C"],
    "Consequence": ["con11,con12,con13", "con21", ".,.,.,.,."],
    "Ensembl_geneid": ["gene11,.,gene13", "gene21", ".,.,.,.,."],
    "Ensembl_proteinid": ["prot11,.,prot13", "prot21", ".,.,.,.,."],
    "Ensembl_transcriptid": ["tra11,.,tra13", "tra21", ".,.,.,.,."]
})

for col in reqd_cols:
    df[col] = df[col].str.split(pat=",", expand=False)

df = df.explode(column=reqd_cols, ignore_index=True)

print(df.info(verbose=True))
print(df.head())
### Pandas implementation end

### Dask implementation start, does not work
df = ddf.from_pandas(
    data=pd.DataFrame({
        "CHROM": [1, 1, 2],
        "POS": [10000, 11000, 20000],
        "ID": ["1-10000-A-C", "1-11000-A-G", "2-20000-T-C"],
        "REF": ["A", "A", "T"],
        "ALT": ["C", "G", "C"],
        "Consequence": ["con11,con12,con13", "con21", ".,.,.,.,."],
        "Ensembl_geneid": ["gene11,.,gene13", "gene21", ".,.,.,.,."],
        "Ensembl_proteinid": ["prot11,.,prot13", "prot21", ".,.,.,.,."],
        "Ensembl_transcriptid": ["tra11,.,tra13", "tra21", ".,.,.,.,."]
    }),
    npartitions=1
)

for col in reqd_cols:
    df[col] = df[col].str.split(pat=",", n=-1, expand=False)

df = df.explode(column=reqd_cols)

print(df.info(verbose=True))
print(df.head())
### Dask implementation end
python pandas dask dask-dataframe
1个回答
0
投票

Dask 2023.7.1:

如果安装了 pandas>=2 和 pyarrow>=12,Dask DataFrame 将使用对象数据类型自动将文本数据转换为 string[pyarrow]。

为了避免这种情况,您可以在创建 Dask Dataframe 之前停用此功能,只需添加:

import dask
dask.config.set({"dataframe.convert-string": False})

在创建你的之前,它解决了问题。

© www.soinside.com 2019 - 2024. All rights reserved.