<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Finding a Consensus Sequence
This code is implementation of Chapter 2 from Bioinformatics Algorithms (Pevzner, Compeau).
Step1:  Now we have a DataFrame where we can get all the bases in each position to find the base(s) occurring most frequently.  We'll create a second DataFrame where the less frequent bases are put into lowercase.  We'll also create a profile that gives us the frequency as a percentage.  Note that we can create DataFrame of zeros easily, but we need the percentage profile to be initialized with "0." to indicate that we will store floats not integers.
Lastly, we'll create a "simple consensus" that simply uses the singly most frequently occurring base.  When there is a tie, a random base is chosen.
Step2:  For the "real" consensus, we'll take into account all bases occurring at a frequency of 40% or greater.
<ASSISTANT_TASK:>
Python Code:
import pandas as pd
from collections import Counter
   
seqs = ['TCGGGGGTTTTT', 
        'CCGGTGACTTAC', 
        'ACGGGGATTTTC', 
        'TTGGGGACTTTT',
        'AAGGGGACTTCC',
        'TTGGGGACTTCC',
        'TCGGGGATTCAT',
        'TCGGGGATTCCT',
        'TAGGGGACCTAC',
        'TCGGGTATAACC']
data = {}
for i, seq in enumerate(seqs):
    data[i+1] = list(seq)
df = pd.DataFrame(data).T
df
Explanation: Finding a Consensus Sequence
This code is implementation of Chapter 2 from Bioinformatics Algorithms (Pevzner, Compeau).
End of explanation
freq_df = pd.DataFrame()
nucs = list('ACGT')
num_seqs = len(seqs)
counts_df = pd.DataFrame(0, index=nucs, columns=list(range(num_seqs)))
profile_df = pd.DataFrame(0., index=nucs, columns=list(range(num_seqs)))
simple_consensus = []
for col in df.columns:
    bases = df[col].values.tolist()
    base_count = Counter(bases)
    most_common = max(set(bases), key=bases.count)
    simple_consensus.append(most_common)
    
    freq_df[col] = list(map(lambda b: b if b == most_common else b.lower(), bases))
    
    for nuc in nucs:
        counts_df.at[nuc, col] = base_count[nuc]
        profile_df.at[nuc, col] = base_count[nuc] / len(seqs)
print('Consensus')
print(''.join(simple_consensus))
print('Frequency')
freq_df
print('Counts')
counts_df
print('Profile')
profile_df
scores = []
for col in freq_df:
    bases = freq_df[col].values.tolist()
    lower = list(filter(lambda b: b.islower(), bases))
    scores.append(len(lower))
    
print(scores)
print(sum(scores))
Explanation: Now we have a DataFrame where we can get all the bases in each position to find the base(s) occurring most frequently.  We'll create a second DataFrame where the less frequent bases are put into lowercase.  We'll also create a profile that gives us the frequency as a percentage.  Note that we can create DataFrame of zeros easily, but we need the percentage profile to be initialized with "0." to indicate that we will store floats not integers.
Lastly, we'll create a "simple consensus" that simply uses the singly most frequently occurring base.  When there is a tie, a random base is chosen.
End of explanation
consensus = []
for col in profile_df.columns:
    profile = profile_df[col]
    max_bases = profile[profile >= .4].index.tolist()
    consensus.append('/'.join(max_bases))
    
print('Consensus')
print('  '.join(consensus))
Explanation: For the "real" consensus, we'll take into account all bases occurring at a frequency of 40% or greater.
End of explanation
<END_TASK>