为什么这个函数会原地改变pd.DataFrame?

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

就地改变对我来说仍然总是有点奇怪。这是我的代码:

import pandas as pd
import numpy as np


def sort_variantsdf(variantdf_orig):

    variantdf['variantindex'] = variantdf.index
    variantdf[['chrom', 'pos', 'ref', 'alt_tmp']] = variantdf['variant'].str.split('_', expand=True)
    variantdf['alt'] = np.where(variantdf.alt_tmp.isna(),
                                variantdf.ref,
                                variantdf.alt_tmp)
    variantdf['ref'] = np.where(variantdf.alt_tmp.isna(),
                                variantdf.alt_tmp,
                                variantdf.ref)
    variantdf = variantdf.drop('alt_tmp', axis='columns')
    variantdf['pos'] = variantdf['pos'].astype('int64')
    variantdf = variantdf.sort_values(['chrom', 'pos', 'ref', 'alt'])
    variantdf = variantdf.drop(['chrom', 'pos', 'ref', 'alt'], axis='columns')

    return variantdf


def resort_variantsdf(variantdf_sorted):
    return variantdf_sorted.sort_values('variantindex').drop('variantindex', axis='columns')


if __name__ == '__main__':
    vars = pd.DataFrame({'variant': ['1_100_A_C', '2_300_A_C', '3_300_C', '2_200_C']})

    vars_sorted = sort_variantsdf(vars)
    vars_resorted = resort_variantsdf(vars_sorted)

    print(vars)
    print()
    print(vars_sorted)
    print()
    print(vars_resorted)
    print()
    print(vars.equals(vars_resorted))

导致此输出:

     variant  variantindex chrom  pos   ref alt_tmp alt
0  1_100_A_C             0     1  100     A       C   C
1  2_300_A_C             1     2  300     A       C   C
2    3_300_C             2     3  300  None    None   C
3    2_200_C             3     2  200  None    None   C

     variant  variantindex
0  1_100_A_C             0
3    2_200_C             3
1  2_300_A_C             1
2    3_300_C             2

     variant
0  1_100_A_C
1  2_300_A_C
2    3_300_C
3    2_200_C

False

添加

variantdf = variantdf_orig.copy()
(并将参数名称更改为
variantdf_orig
解决了这个问题。我仍然认为,因为它是函数中的新变量名称,所以这不应该改变任何内容。对我来说最大的问题是:

为什么只改变到第一个

.drop
之前的部分?

此外,如果我使用 Polars 制作类似的函数并将旧变量名称分配给新变量名称,这不会改变任何内容:

def sort_variantsdf(variantdf):

    variantdf = variantdf.with_row_index(
        'variantindex'
    ).with_columns(
        pl.col('variant')
        .str.split_exact('_', 3)
        .struct.rename_fields(['chrom', 'pos', 'ref', 'alt_tmp'])
        .alias('fields')
    ).unnest(
        'fields'
    ).with_columns(
        alt = pl.when(pl.col('alt_tmp').is_null()).then(pl.col('ref')).otherwise(pl.col('alt_tmp')),
        ref = pl.when(pl.col('alt_tmp').is_null()).then('alt_tmp').otherwise(pl.col('ref'))
    ).drop(
        'alt_tmp'
    ).with_columns(
        pl.col('pos').cast(pl.Int64)
    ).sort(
        'chrom', 'pos', 'ref', 'alt'
    ).drop(
        'chrom', 'pos', 'ref', 'alt'
    )
pandas
1个回答
0
投票

我的第一个观察结果是您的

sort_variantsdf()
函数有一个名为
variantdf_orig
的输入参数。但是,在函数定义内部,您根本不使用它 - 相反,您正在处理一个名为
variantdf
的不同变量。这就是为什么当您添加
variantdf = variantdf_orig.copy()
(我假设在
sort_variantsdf()
函数的第一行)时,它可以正常工作。

如果我是你,我就会更换线路

def sort_variantsdf(variantdf_orig):

def sort_variantsdf(variantdf):

我不确定这是否能回答您的问题,但可能值得一试。

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