【问题标题】:Find the difference between strings for each two rows of pandas data.frame查找每两行 pandas data.frame 的字符串之间的差异
【发布时间】:2020-04-12 14:29:09
【问题描述】:

我是 python 新手,我为此苦苦挣扎了一段时间。 我有一个看起来像这样的文件:

    name   seq
1   a1     bbb
2   a2     bbc
3   b1     fff
4   b2     fff
5   c1     aaa
6   c2     acg

其中 name 是字符串的名称,seq 是字符串。 我想要一个新列或一个新数据框,指示每两行之间没有重叠的差异数量。例如,我想要名称 [a1-a2] 然后 [b1-b2] 和最后 [c1-c2] 之间的序列之间的差异数。

所以我需要这样的东西:

    name   seq   diff  
1   a1     bbb    NA   
2   a2     bbc    1
3   b1     fff    NA
4   b2     fff    0
5   c1     aaa    NA
6   c2     acg    2

非常感谢任何帮助

【问题讨论】:

  • 您尝试解决什么问题?是否总是两行以相同的字符开头?
  • 是的,它们以相同的字母开头,它们之间的唯一区别是末尾的数字。
  • 每个字母总是有两个序列吗? @LDT
  • 是的,它们按照示例中的指示进行排序
  • 嘿@LDT 我认为你有三个正确的解决方案两个你的问题。我倾向于建议您接受 yatu 或 anky 的版本,因为它们更稀疏/更高效,并且还具有更高的灵活性(超过我的)。

标签: python string pandas difference


【解决方案1】:

看起来您想要字符串对中的jaccard distance。这是使用groupbyscipy.spatial.distance.jaccard 的一种方法:

from scipy.spatial.distance import jaccard
g = df.groupby(df.name.str[0])

df['diff'] = [sim for _, seqs in g.seq for sim in 
              [float('nan'), jaccard(*map(list,seqs))]]

print(df)

  name  seq  diff
1   a1  bbb   NaN
2   a2  bbc   1.0
3   b1  fff   NaN
4   b2  fff   0.0
5   c1  aaa   NaN
6   c2  acg   2.0

【讨论】:

  • 不错,直到:jaccard 我立即想到Levenshtein 看到这个。 :)
  • 啊,那太好了 :) mm 听起来也是一个选项,虽然@anky 记不起相似性度量到底是什么
  • 赞成您的两个答案,因为您对字符串距离测量 (?) 的了解以及代码-sn-ps 的效率给我留下了深刻的印象
  • 非常感谢亚图。我想问你。如果我的 data.frame 中的“名称”是这样的 [1,1], [2,2], [3,3] 而不是 [a1,a2], [b1,b2] , [c1,c2] 什么我需要更改您的代码吗?
  • 使用df.groupby(df.index//2@LDT
【解决方案2】:

替代Levenshtein距离:

import Levenshtein
s = df['name'].str[0]
out = df.assign(Diff=s.drop_duplicates(keep='last').map(df.groupby(s)['seq']
                    .apply(lambda x: Levenshtein.distance(x.iloc[0],x.iloc[-1]))))

  name  seq  Diff
1   a1  bbb   NaN
2   a2  bbc   1.0
3   b1  fff   NaN
4   b2  fff   0.0
5   c1  aaa   NaN
6   c2  acg   2.0

【讨论】:

  • 非常感谢你。我想问你。如果我的 data.frame 中的“名称”是这样的 [1,1], [2,2], [3,3] 而不是 [a1,a2], [b1,b2] , [c1,c2] 什么我需要更改您的代码吗?
  • @LDT 然后将s 更改为s = df['name'] 而不是s = df['name'].str[0]
  • 非常感谢。你救了我@anky。节日快乐。也感谢您回答我的问题
【解决方案3】:

作为第一步,我使用以下方法重新创建了您的数据:

#!/usr/bin/env python3
import pandas as pd

# Setup
data = {'name': {1: 'a1', 2: 'a2', 3: 'b1', 4: 'b2', 5: 'c1', 6: 'c2'}, 'seq': {1: 'bbb', 2: 'bbc', 3: 'fff', 4: 'fff', 5: 'aaa', 6: 'acg'}}
df = pd.DataFrame(data)

解决方案 您可以尝试迭代数据框并将最后一次迭代的seq 值与当前值进行比较。为了比较两个字符串(存储在数据框的 seq 列中),您可以应用一个简单的列表理解,例如在此函数中:

def diff_letters(a,b):
    return sum ( a[i] != b[i] for i in range(len(a)) )

迭代数据框行

diff = ['NA']

row_iterator = df.iterrows()
_, last = next(row_iterator)

# Iterate over the df get populate a list with result of the comparison
for i, row in row_iterator:
    if i % 2 == 0:
        diff.append(diff_letters(last['seq'],row['seq']))
    else:
        # for odd row numbers append NA value
        diff.append("NA")
    last = row
df['diff'] = diff

结果如下所示

  name  seq diff
1   a1  bbb   NA
2   a2  bbc    1
3   b1  fff   NA
4   b2  fff    0
5   c1  aaa   NA
6   c2  acg    2

【讨论】:

    【解决方案4】:

    检查这个

    import pandas as pd
    
    data = {'name':  ['a1', 'a2','b1','b2','c1','c2'],
        'seq': ['bbb', 'bbc','fff','fff','aaa','acg']
        }
    
    df = pd.DataFrame (data, columns = ['name','seq'])
    diffCntr=0
    df['diff'] = np.nan
    i=0
    while i < len(df)-1:
        diffCntr=np.nan
        item=df.at[i,'seq']
        df.at[i,'diff']=diffCntr
        diffCntr=0
        for j in df.at[i+1,'seq']:
            if item.find(j) < 0:
                diffCntr +=1
        df.at[i+1,'diff']=diffCntr
        i +=2    
    df  
    

    结果是这样的:

        name seq    diff
    0   a1   bbb    NaN
    1   a2   bbc    1.0
    2   b1   fff    NaN
    3   b2   fff    0.0
    4   c1   aaa    NaN
    5   c2   acg    2.0
    

    【讨论】:

    • 非常感谢罗拉。我想问你。如果我的 data.frame 中的“名称”是这样的 [1,1], [2,2], [3,3] 而不是 [a1,a2], [b1,b2] , [c1,c2] 什么我需要更改您的代码吗?
    • @LDT 代码中没有任何改变。您只需将 df 中的数据更改为 1,1,2,2,3,3 而不是 a1,a2,b1,b2,c1,c2 。我的代码跟踪 df 记录并比较每两个后续行中的“seq”值,而不管“name”列中插入的值如何。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-08
    • 2021-09-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多