0
$\begingroup$

I have read the content of a text file into pandas and needed some help matching the pattern.

Here is the pattern, where a can any number greater than zero and b can be zero or any number greater than zero:

father=a|0 || 0|a
mother=a|0 || 0|a
daughter1=b|0 || 0|b
daughter2=a|0 || 0|a
daughter3=b|0 || 0|b
son1=a|0 || 0|a
son2=b|0 || 0|b

Here is the function that reads the content of text file to pandas

import pandas as pd
def read():
    varian=pd.read_csv('file.txt',sep = "\t")

father=varian["FATHER"]
mother=varian["MOTHER"]
daughter1=varian["DAUGHTER1"]
daughter2=varian["DAUGHTER2"]
daughter3=varian["DAUGHTER3"]
son1=varian["SON1"]
son2=varian["SON2"]

The content of the file looks like this

HROM    POS REF ALT FATHER  MOTHER  DAUGHTER1   DAUGHTER2   DAUGHTER3   SON1    SON2    INFO    FREQUECY
1   1226852 G   C   1/0 0/0 1|0 1|0 1|0 1|0 0|0 AN=2184;AC=12   0.005494505
1   1847936 C   T   0/1 1/1 1|1 1|1 1|1 1|1 0|1 AC=1;AN=2184    0.000457875
1   2428427 C   G   0/1 0/0 0|0 0|0 0|0 0|0 1|0 AC=4;AN=2184    0.001831502
1   2515616 G   A   1/0 1/0 1/0 1|1 1|1 1/0 1/0 AC=1;AN=2184    0.000457875
1   3801895 T   C   1/0 1/0 0|0 1/0 1/0 0|0 1|1 AC=10;AN=2184   0.004578755
$\endgroup$
  • 2
    $\begingroup$ Is that really what your file looks like? Doesn't the first line start with #CHROM? Does it really start with HROM? Also, please look at our formatting tools to see how to format your posts correctly and avoid confusion. $\endgroup$ – terdon Oct 14 at 8:48
  • $\begingroup$ Sorry for the delay, busy week, done below $\endgroup$ – Michael G. Oct 18 at 7:19
0
$\begingroup$

This is not a bioinformatics question, but a basic pandas question, so SO is a better place for this... But your odd looking VCF file can be parsed as follows without even using regex:

import pandas as pd

def splitter(cell, key):
    parts = cell.split('||')
    if key in parts[0]:
         p = parts[0].split('|')
    else:
         p = parts[1].split('|')
    sp = [x.strip() for x in p if key not in x]
    return float(sp[0])

def read():
    splitter_a = lambda v: v.split('||')[0].split('|')[1]) 
    varian=pd.read_csv('file.txt',sep = "\t")
    a_splitter = lambda c: splitter(c, 'a')
    b_splitter = lambda c: splitter(c, 'b')
    varian = varian.assign(father_a=varian.FATHER.apply(a_splitter)\
              .assign(father_a=varian.FATHER.apply(b_splitter)\
              .assign(mother_a=varian.MOTHER.apply(la_splitter)\

etc.

display(varian) or print(varian.columns) will show that you have new columns called father_a etc.

$\endgroup$
  • $\begingroup$ pandas regex might still help, but re isn't needed. The concept might work. ... It's a pandas solution for sure. I like the style. I'd construct a mask and then filter the columns. They are wanting to exclude homozygotes $\endgroup$ – Michael G. Oct 16 at 13:24
  • $\begingroup$ The immediate issue is the separator can be '/' as well $\endgroup$ – Michael G. Oct 16 at 13:27
1
$\begingroup$

Its easy. You want to remove homozygotes and here is the solution for the FATHER class. Note the MOTHER class will comprise homozygotes in the answer because you are only searching for FATHER. To perform an intersection one approach is just to concatenate the mask.

import pandas as pd

genedict = {\
            'FATHER': ['1/0', '1/1', '0/0', '1/0', '0/1'], \
            'MOTHER': ['1/1', '1/1', '1/0', '1/0', '0/0']}

df = pd.DataFrame(genedict)    
mask = df.FATHER.str.contains(r'1[|/]0') + df.FATHER.str.contains(r'0[|/]1')
df[mask]

OUTPUT

  FATHER MOTHER
0    1/0    1/1
3    1/0    1/0
4    0/1    0/0

Note, this is not your original dataset, its a dictionary to demonstrate the principle and note all your other columns will carry across unless you want to 'drop' them. Finally, pandas has its own regex system, regardless the traditional r'' code is still needed

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.