繁体   English   中英

熊猫:for循环通过列

[英]Pandas: for loop through columns

我的数据如下:

SNP Name ss715583617 ss715592335 ss715591044 ss715598181
4    PI081762           T           A           A           T
5   PI101404A           T           A           A           T
6   PI101404B           T           A           A           T
7    PI135624           T           A           A           T
8    PI326581           T           A           A           T
9   PI326582A           T           A           A           T
10  PI326582B           T           A           A           T
11   PI339732           T           A           A           T
12  PI339735A           T           A           A           T
13  PI339735B           T           A           A           T
14  PI342618A           T           A           A           T

实际上,我有479行的50,000列的数据集。 我的目标是遍历每一列中的字符,然后根据哪个是最丰富的字符将数据转换为整数。

现在,我有数据输入,或多或少地编写了我想用来分别分析每一列的函数。 但是,我不太了解如何在数据集中的所有列中使用forloop或使用apply函数。 我不希望对列进行硬编码,因为我将要分析40,000〜50,000列。

到目前为止,我的代码是:

import pandas as pd

df = pd.read_csv("/home/dfreese/Desktop/testSNPtext", delimiter='\t')

df.head() # check that the file format fits

# ncol df
df2 = df.iloc[4:-1] # Select the rows you want to analyze in a subset df
print(df2)

我的功能:

def countAlleles(N): 
    # N is just suppose to be the column, ideally once I've optimized the function
    # I need to analyze every column 

    # Will hold the counts of each letter in the column
    letterCount = [] 
    # This is a parallel array to know the order
    letterOrder = {'T','A','G','C','H','U'}  


    # Boolean to use which one is the maximum 
    TFlag = None 
    AFlag = None 
    GFlag = None
    CFlag = None
    HFlag = None
    UFlag = None 

# Loop through the column to determine which one is the maximum 
for i in range(len(N)): # How do I get index information of the column?
    if(N[i] == 'T'): # If the element in the column is T
        letterCount[0] = letterCount[0] + 1
    elif(N[i] == 'A'):
        letterCount[1] = letterCount [1] + 1
    elif (N[i] == 'G'):
        letterCount[2] = letterCount [2] + 1
    elif (N[i] == 'C'):
        lettercount[3] = letterCount[3] + 1
    elif(N[i] == 'H'):
        letterCount[4] = letterCount[4] + 1
    else:
        letterCount[5] = letterCount[5] + 1

max = letterCount[0] # This will hold the value of maximum
mIndex = 0 # This holds the index position with the max value

# Determine which one is max
for i in range(len(letterCount)):
    if (letterCount[i] > max):
        max = letterCount[i]
        mIndex = i

所以我设计了输入列的功能,希望能够遍历数据框的所有列。 我的主要问题是:

1)我如何将每一列中的每一个作为参数通过每一列的元素传递给for循环?

我最困惑的原因是大熊猫如何使用索引。 我熟悉C ++和Java中的二维数组,而这正是我所学知识的大部分来源。

我正在尝试使用apply函数:

df2 = df2.apply(countAlleles('ss715583617'), axis=2)

但似乎我的申请不正确。

更新的答案 :现在,根据每列等位基因的出现情况,对数据框进行分析并替换为int值。 如果一个等位基因的发生次数与另一个等位基因相同,则发生的问题仍然相同-分配将不是唯一的。

import pandas as pd                                                              
import numpy as np                                                               

df = pd.DataFrame.from_dict({"ss1": ["T", "T", "T", "G"],                        
                             "ss2": ["G", "G", "T", "A"],                        
                             "ss3": ["C", "H", "C", "H"]})                       

letterOrder = np.array(['T', 'A', 'G', 'C', 'H', 'U'])                           

for col in df:                                                                   
    alleles = list()                                                             
    for num, allele in enumerate(letterOrder):                                   
        alleles.append(df[col].str.count(allele).sum())                          

    # dictionary with full sorted keys                                           
    repl = letterOrder[np.argsort(alleles)][::-1]                                
    # directly replace chars by value                                            
    for num, char in enumerate(repl):                                            
        df[col].replace(char, num+1, inplace=True)                               

print(df)

这将更改初始数据框

  ss1 ss2 ss3
0   T   G   C
1   T   G   H
2   T   T   C
3   G   A   H

到新数据框,并根据出现次数对int进行排序:

   ss1  ss2  ss3
0    1    1    2
1    1    1    1
2    1    3    2
3    2    2    1

作为参考,给出了最大列索引的答案:

import pandas as pd                                                              
import numpy as np                                                               
from collections import OrderedDict                                              

df = pd.DataFrame.from_dict({"ss1": ["T", "T", "T", "G"],                                     
                             "ss2": ["G", "G", "T", "A"],                           
                             "ss3": ["C", "H", "C", "H"]})                          

letterOrder = ['T', 'A', 'G', 'C', 'H', 'U']                                        

full_results = OrderedDict()                                                        
for col in df:                                                                      
    alleles = list()                                                                
    for num, allele in enumerate(letterOrder):                                      
        alleles.append(df[col].str.count(allele).sum())                             

    full_results[col] = [letterOrder[np.argmax(alleles)], np.max(alleles)]       

print(full_results)

这将给:

OrderedDict([('ss1', ['T', 3]), ('ss2', ['G', 2]), ('ss3', ['C', 2])])

dict中的键是列的名称,值是带有[allele,number_of_occurences]的列表。

我使用OrderedDict来保持列和名称的顺序,但是如果不需要该顺序,则可以使用dict ,或者如果不需要列名称(并且隐式ID足够),请使用list

但请注意 :如果在一列中两个(或多个)字符的计数相同,则只会返回其中一个。 您将需要为此添加其他测试。

要遍历例如for循环中的列,请使用list(df) 无论如何,您可以轻松地执行使用collections.Counter尝试。

假设数据帧为df

df
#         Name ss715583617 ss715592335 ss715591044 ss715598181
#0    PI081762           T           A           A           T
#1   PI101404A           T           A           A           T
#2   PI101404B           T           A           A           T
#3    PI135624           T           A           A           T
#4    PI326581           T           A           F           D
#5   PI326582A           G           A           F           T
#6   PI326582B           G           A           A           T
#7    PI339732           D           H           A           T
#8   PI339735A           D           A           A           T
#9   PI339735B           A           A           A           T
#10  PI342618A           D           A           A           T

我从评论部分和您的原始帖子中收集到的信息,您希望根据出现频率替换每列中的每个字符。 这是一种方法:

做柜台

from collections import Counter

cols       = [ col for col in list(df) if col not in ['Name'] ] # all the column you want to operate on
col_counters = { col: Counter( df[col] ) for col in cols } 
#{'ss715583617': Counter({'T': 5, 'D': 3, 'G': 2, 'A': 1}),
# 'ss715591044': Counter({'A': 9, 'F': 2}),
# 'ss715592335': Counter({'A': 10, 'H': 1}),
# 'ss715598181': Counter({'T': 10, 'D': 1})}

对每个计数器中的项目进行排序

sort_func = lambda items: sorted(items, key=lambda x:x[1], reverse=True ) # sort a nested list according to second element in each sublist
sort_result = { col: sort_func(counter.items()) for col,counter in col_counters.iteritems() }
#{'ss715583617': [('T', 5), ('D', 3), ('G', 2), ('A', 1)],
# 'ss715591044': [('A', 9), ('F', 2)],
# 'ss715592335': [('A', 10), ('H', 1)],
# 'ss715598181': [('T', 10), ('D', 1)]}

根据排序结果替换数据框中的字母

在这里,我们将使用enumerate获取每个排序结果的位置

mapper = { col: {letter:i+1 for i,letter in enumerate(sort_result[col]) } for col in sort_result } 
#{'ss715583617': {'A': 4, 'D': 2, 'G': 3, 'T': 1},
# 'ss715591044': {'A': 1, 'F': 2},
# 'ss715592335': {'A': 1, 'H': 2},
# 'ss715598181': {'D': 2, 'T': 1}}

df.replace( to_replace=mapper, inplace=True)
#         Name  ss715583617  ss715592335  ss715591044  ss715598181
#0    PI081762            1            1            1            1
#1   PI101404A            1            1            1            1
#2   PI101404B            1            1            1            1
#3    PI135624            1            1            1            1
#4    PI326581            1            1            2            2
#5   PI326582A            3            1            2            1
#6   PI326582B            3            1            1            1
#7    PI339732            2            2            1            1
#8   PI339735A            2            1            1            1
#9   PI339735B            4            1            1            1
#10  PI342618A            2            1            1            1

这应该足以让您上路。 我不确定如何处理重复的元素,例如,如果列中的T和G具有相同的编号,那么我将如何处理这些重复的元素。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM