gpt4 book ai didi

python - Pandas 系列 : compare values all vs. 所有

转载 作者:行者123 更新时间:2023-11-28 18:14:33 44 4
gpt4 key购买 nike

我有一个包含两列的 DataFrame:sequenceid 例如:

import pandas as pd
data = {"id":["seq1", "seq2", "seq3"], "sequence":["ATCTGC", "AACTGC", "AACTCC"]}
df = pd.DataFrame(data)

(这是 +20k 序列的实际数据集的一个小例子)

我正在尝试以一种有效的方式获得序列距离矩阵。距离被理解为每个序列之间不同字符的数量。
为此,我需要在 sequence 列中应用所有值与所有值的函数

我当前的代码如下所示:

def count_differences( seq, df ):
return df.apply(lambda x: sum(1 for i, j in zip(x["sequence"], seq) if i != j), axis=1)

df2 = df.apply(lambda x: count_differences( x["sequence"], df), axis=1)
df2 = df2.rename(df["id"], axis="columns").rename(df["id"], axis="rows")

# seq1 seq2 seq3
# seq1 0 1 2
# seq2 1 0 1
# seq3 2 1 0

这是应用中的应用。它工作正常,但在我拥有的所有序列上运行它时确实需要相当多的时间。

有没有更有效的方法呢?我一直在尝试查看是否可以使用 Series.map 来加快速度,但到目前为止我还没有找到任何解决方案。

最佳答案

这是一个想法,涉及到 numpy

有几个步骤,但由于底层工作是通过 numpy 数值数组完成的,这可能更有效。

import pandas as pd, numpy as np

data = {"id":["seq1", "seq2", "seq3"], "sequence":["ATCTGC", "AACTGC", "AACTCC"]}
df = pd.DataFrame(data)

a = np.array(list(map(list, df['sequence'])))
values = np.unique(a, return_inverse=True)[1].reshape(a.shape)

n = len(a)
d = {(i, j): np.sum(a[i]!=a[j]) for i in range(n) for j in range(n) if j > i}

res = np.zeros((n, n))
keys = list(zip(*d.keys()))

res[keys[0], keys[1]] = list(d.values())
res += res.T

df_res = pd.DataFrame(res, columns=data['id'], index=data['id'], dtype=int)

# seq1 seq2 seq3
# seq1 0 1 2
# seq2 1 0 1
# seq3 2 1 0

解释

  • 将您的序列转换为 numpy 数组,其中每个元素都是一个字母。
  • 使用 np.unique 分解您的数组(即将每个字母与一个数字相关联)。
  • 使用 np.sum 查找因式分解数组中各行之间的字母差异,并将结果添加到字典中。由于您的结果是三角形的,因此只需执行一半的计算。
  • 从字典中创建新的 numpy 数组并添加逆数组使三角数组满。
  • 将您的字典转换为数据框。

性能基准测试

我看到了大约 7 倍的性能提升。

%timeit original(df)  # 3.32s
%timeit jp(df) # 461ms

import pandas as pd, numpy as np

data = {"id":["seq1", "seq2", "seq3"], "sequence":["ATCTGC", "AACTGC", "AACTCC"]}
df = pd.DataFrame(data)

df = pd.concat([df]*100)

def original(df):
def count_differences( seq, df ):
return df.apply(lambda x: sum(1 for i, j in zip(x["sequence"], seq) if i != j), axis=1)

df2 = df.apply(lambda x: count_differences( x["sequence"], df), axis=1)

return df2

def jp(df):

a = np.array(list(map(list, df['sequence'])))
values = np.unique(a, return_inverse=True)[1].reshape(a.shape)

n = len(a)
d = {(i, j): np.sum(a[i]!=a[j]) for i in range(n) for j in range(n) if j > i}

res = np.zeros((n, n))
keys = list(zip(*d.keys()))

res[keys[0], keys[1]] = list(d.values())
res += res.T

df_res = pd.DataFrame(res, columns=range(len(df['id'])), index=range(len(df['id'])), dtype=int)

return df_res

关于python - Pandas 系列 : compare values all vs. 所有,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49235538/

44 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com