代码之家  ›  专栏  ›  技术社区  ›  Christopher

从多个字符串中提取序列

  •  1
  • Christopher  · 技术社区  · 7 年前

    我正在寻找一种解决方案,帮助构造和分析不同长度的序列数据。我需要为机器学习分类器(LSTM)准备数据。我的输入示例如下:

    输入

    ID 1 2 3 4
    0  A B C D
    1  A C D
    2  A D B
    

    其中,columns是序列步数,以及 A,B,C,D,E 某些行为。

    作为 可能的序列 我们期望:

    A,B
    B,C
    C,D
    A,B,C
    B,C,D
    A,C
    A,C,D
    C,D
    A,D
    A,D,B
    D,B
    

    首先,应该打印一个脚本, 某些序列发生的频率 以及到底有多少个序列

    (C,D) 2
    (A,B,C,D) 1
    (A,B) 1
    ...
    

    但更重要的是,为了以后使用,我需要 一个热编码 所有可能的序列,最终结果如下:

    期望输出 以下内容:

    ID  (A,B) (B,C) (C,D) (A,B,C) (B,C,D) (A,C) (A,C,D) (C,D) (A,D) (A,D,B) (D,B)
    0   1     1     1     1       1       0     0       1     0     0    0 
    1   0     0     1     0       0       1     1       1     0     0    0
    2   0     0     0     0       0       0     0       0     1     1    1
    

    在哪里? (A,B) (B,C) 等也可以表示为编码变量。我认为,通过这种方式,数据将以一种考虑序列和子序列进行分类的形式来表示。

    在第一部分中,我阅读了prefixspan,但找不到可复制的代码示例。在我与Scikit Learn和Keras合作的过程中,欢迎使用相关的解决方案!

    尝试:

    import itertools
    import pandas as pd
    d = {'1': ['A', 'A', 'A'], '2': ['B', 'C', 'D'], '3': ['C', 'D', 'B'], '4': ['D', '', '']}
    df = pd.DataFrame(data=d)
    df
    
    list(itertools.combinations(df))
    
    3 回复  |  直到 7 年前
        1
  •  1
  •   SpghttCd    7 年前

    我将尝试将步骤作为字符串,序列作为子字符串:

    import pandas as pd
    
    def get_seq(s):
        return [s[a:b] for a in range(len(s)) for b in range(a+2, len(s)+1)]
    
    df = pd.DataFrame({'steps': ['ABCD', 'ACD', 'ADB']})
    df['seq'] = df.steps.apply(get_seq)
    
    df
    Out: 
      steps                           seq
    0  ABCD  [AB, ABC, ABCD, BC, BCD, CD]
    1   ACD                 [AC, ACD, CD]
    2   ADB                 [AD, ADB, DB]
    

    第一个请求的结果: 顺序计数器

    all_seq = df.seq.apply(pd.Series).stack().values
    
    all_seq
    Out: 
    array(['AB', 'ABC', 'ABCD', 'BC', 'BCD', 'CD', 'AC', 'ACD', 'CD', 'AD', 'ADB', 'DB'], dtype=object)
    
    df_count = pd.DataFrame({'seq': all_seq, 'cntr': 1})
    
    df_count.groupby('seq').count().T            # .T only for shorter output here below
    Out: 
    seq   AB  ABC  ABCD  AC  ACD  AD  ADB  BC  BCD  CD  DB
    cntr   1    1     1   1    1   1    1   1    1   2   1
    

    第二个请求结果: 一个热编码表

    df_ohe = pd.DataFrame()
    for seq in set(all_seq):
        df_ohe[seq] = df.steps.str.contains(seq)
    
    df_ohe
    Out: 
        ABCD    BCD     AC     AB    ABC     AD    ADB     DB     BC    ACD     CD
    0   True   True  False   True   True  False  False  False   True  False   True
    1  False  False   True  False  False  False  False  False  False   True   True
    2  False  False  False  False  False   True   True   True  False  False  False
    

    或者如果你更喜欢零和一:

    df_ohe.astype(int)
    Out: 
       ABCD  BCD  AC  AB  ABC  AD  ADB  DB  BC  ACD  CD
    0     1    1   0   1    1   0    0   0   1    0   1
    1     0    0   1   0    0   0    0   0   0    1   1
    2     0    0   0   0    0   1    1   1   0    0   0
    
        2
  •  1
  •   Hamid Mir    7 年前

    我没有得到在输出中转到下一行的限制,但是您可以通过字典计算出现的次数:

    data = ['AB',
    'BC',
    'CD',
    'ABC',
    'BCD',
    'AC',
    'ACD',
    'CD',
    'AD',
    'ADB',
    'DB']
    matrix={}
    for i in data:
        if i in matrix:
            matrix[i] +=1 
        else:
            matrix[i] =1
    
    print(matrix)
    

    输出:'bcd':1,'ad':1,'db':1,'ab':1,'abc':1,'ac':1,'bc':1,'adb':1,'acd':1,'cd':2

    这种方法对输入顺序很敏感。如果有问题,我必须更新它

        3
  •  1
  •   ragnar    7 年前

    我会用一个柜台:

    from collections import Counter
    
    def get_all_subsequence(seq):
        return [seq[i:j] for i in range(len(seq)) for j in range(i + 2, len(seq) + 1)]
    
    input = ["ABCD", "ACD", "ADB"]
    
    counter = Counter()
    for entry in input:
        counter.update(get_all_subsequence(entry))
    print(counter.most_common())
    [('CD', 2), ('AB', 1), ('ABC', 1), ('ABCD', 1), ('BC', 1), ('BCD', 1), ('AC', 1), 
    ('ACD', 1), ('AD', 1), ('ADB', 1), ('DB', 1)]