从多个字符串中提取序列

时间:2018-06-27 10:36:07

标签: python keras sequence categorical-data

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

输入

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

其中的列是顺序步骤和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 个答案:

答案 0 :(得分:1)

我没有得到输出下一行的限制,但是您可以按字典来计算出现次数:

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}

此方法对输入顺序敏感。如果有关系,那么我必须对其进行更新

答案 1 :(得分:1)

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

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)

我要使用一个计数器:

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)]