¿Cómo leer dos líneas de un archivo y crear claves dinámicas en un bucle for?

En los siguientes datos, estoy tratando de ejecutar un modelo simple de Markov.

Digamos que tengo un dato con la siguiente estructura:

pos M1 M2 M3 M4 M5 M6 M7 M8 hybrid_block S1 S2 S3 S4 S5 S6 S7 S8 1 ATTAAGACA|CCGCTTAGA 2 TGCTGTTGT|AATATCAAT 3 CAACAGTCC|GGACGCGCG 4 GTGTATCTG|TCTTTATCT 

El bloque M representa datos de un conjunto de categorías, al igual que el bloque S.

Los datos son las strings que se hacen conectando letras a lo largo de la línea de posición. Entonces, el valor de la cadena para M1 es ATCG , y también lo es para cada otro bloque.

También hay un hybrid block que tiene dos cadenas que se leen de la misma manera. La pregunta es si quiero encontrar qué cadena en el bloque híbrido es más probable que provenga de qué bloque (M vs. S).

Estoy tratando de construir un modelo de Markov que pueda ayudarme a identificar qué cadena en el hybrid block proviene de qué bloques. En este ejemplo, puedo decir que en el bloque híbrido ATCG provino del block M y CAGT provino del block S

Estoy dividiendo el problema en diferentes partes para leer y extraer los datos:

Nivel de problema 01:

  • Primero leo la primera línea (el encabezado) y creo unique keys para todas las columnas.
  • Luego leo la segunda línea ( pos con valor 1 ) y creo otra clave. En la misma línea leo el valor de hybrid_block y leo el valor de las cadenas. El pipe | es solo un separador, por lo que dos cadenas están en el index 0 and 2 como A y C Entonces, todo lo que quiero de esta línea es un

defaultdict(, {'M1': ['A'], 'M2': ['T'], 'M3': ['T']...., 'hybrid_block': ['A'], ['C']...}

A medida que avanzo con la lectura de la línea, quiero agregar los valores de las cadenas de cada columna y finalmente crear.

defaultdict(, {'M1': ['A', 'T', 'C', 'G'], 'M2': ['T', 'G', 'A', 'T'], 'M3': ['T', 'C', 'A', 'G']...., 'hybrid_block': ['A', 'T', 'C', 'G'], ['C', 'A', 'G', 'T']...}

Nivel de problema 02:

  • Leí los datos en hybrid_block para la primera línea, que son A and C

  • Ahora, quiero crear keys' but unlike fixed keys, these key will be generated while reading the data from bloques keys' but unlike fixed keys, these key will be generated while reading the data from híbridos . For the first line since there are no preceding line the . For the first line since there are no preceding line the teclas will simply be AgA and CgC, which means (A given A, and C given C), and for the values I count the number of A in bloque M and bloque S`. Por lo tanto, los datos se almacenarán como:

defaultdict(, {'M': {'AgA': [4], 'CgC': [1]}, 'S': {'AgA': 2, 'CgC': 2}}

A medida que leo otras líneas, quiero crear nuevas claves basadas en cuáles son las cadenas en el hybrid block y contar el número de veces que esa cadena estuvo presente en el bloque M vs S dada la cadena en la línea precedente. Eso significa que las keys al leer la line 2 serían TgA' which means (T given A) and AgC. For the values inside this key I count the number of times I found TgA' which means (T given A) and AgC. For the values inside this key I count the number of times I found T en esta línea, después de A en la línea anterior and same for AcG`.

El punto por defaultdict después de leer 3 líneas sería.

defaultdict(, {'M': {'AgA': 4, 'TgA':3, 'CgT':2}, {'CgC': [1], 'AgC':0, 'GgA':0}, 'S': {'AgA': 2, 'TgA':1, 'CgT':0}, {'CgC': 2, 'AgC':2, 'GgA':2}}

Entiendo que esto parece demasiado complicado. Pasé por varios dictionary y tutoriales defaultdict pero no pude encontrar una manera de hacerlo.

La solución a cualquier parte si no ambas es muy apreciada.

configuración de pandas

 from io import StringIO import pandas as pd import numpy as np txt = """pos M1 M2 M3 M4 M5 M6 M7 M8 hybrid_block S1 S2 S3 S4 S5 S6 S7 S8 1 ATTAAGACA|CCGCTTAGA 2 TGCTGTTGT|AATATCAAT 3 CAACAGTCC|GGACGCGCG 4 GTGTATCTG|TCTTTATCT """ df = pd.read_csv(StringIO(txt), delim_whitespace=True, index_col='pos') df 

introduzca la descripción de la imagen aquí

solución

en su mayoría pandas con algunos numpy


  • columna híbrida dividida
  • anteponer primera fila idéntica
  • agregue con la versión 'AgA' de self para obtener cadenas de tipo 'AgA'

 d1 = pd.concat([df.loc[[1]].rename(index={1: 0}), df]) d1 = pd.concat([ df.filter(like='M'), df.hybrid_block.str.split('|', expand=True).rename(columns='H{}'.format), df.filter(like='S') ], axis=1) d1 = pd.concat([d1.loc[[1]].rename(index={1: 0}), d1]) d1 = d1.add('g').add(d1.shift()).dropna() d1 

introduzca la descripción de la imagen aquí

Asignar bloques convenientes a sus propios nombres de variables

 m = d1.filter(like='M') s = d1.filter(like='S') h = d1.filter(like='H') 

Cuente cuántos hay en cada bloque y concatene

 mcounts = pd.DataFrame( (m.values[:, :, None] == h.values[:, None, :]).sum(1), h.index, h.columns ) scounts = pd.DataFrame( (s.values[:, :, None] == h.values[:, None, :]).sum(1), h.index, h.columns ) counts = pd.concat([mcounts, scounts], axis=1, keys=['M', 'S']) counts 

introduzca la descripción de la imagen aquí

Si realmente quieres un diccionario.

 d = defaultdict(lambda:defaultdict(list)) dict_df = counts.stack().join(h.stack().rename('condition')).unstack() for pos, row in dict_df.iterrows(): d['M']['H0'].append((row.loc[('condition', 'H0')], row.loc[('M', 'H0')])) d['S']['H0'].append((row.loc[('condition', 'H0')], row.loc[('S', 'H0')])) d['M']['H1'].append((row.loc[('condition', 'H1')], row.loc[('M', 'H1')])) d['S']['H1'].append((row.loc[('condition', 'H1')], row.loc[('S', 'H1')])) dict(d) {'M': defaultdict(list, {'H0': [('AgA', 4), ('TgA', 3), ('CgT', 2), ('GgC', 1)], 'H1': [('CgC', 1), ('AgC', 0), ('GgA', 0), ('TgG', 1)]}), 'S': defaultdict(list, {'H0': [('AgA', 2), ('TgA', 1), ('CgT', 0), ('GgC', 0)], 'H1': [('CgC', 2), ('AgC', 2), ('GgA', 2), ('TgG', 3)]})}