2017-02-15 67 views
2

我有一个矩阵形(600,90亿)保存为*.txt文件。矩阵的每一行由不同的样品名称sample_name1,sample_name2等来命名。但是,存在未标准化的样品名称,例如, s###30023如何用Python统计每个矩阵行的字符?计数器()?

之后,有三个字符的字符串,每个字符长度约90亿字符。

sample_name1 ab2ab222baab22ba2bab2b2aab22ab22bababab2baab2b2a

的矩阵是按以下格式:

600 9123001002 
sample_name1 ab2ab222baab22ba2bab2b2aab22ab22bababab2baab2b2a2bababab2baab2b2ab2a... 
sample_name2 abbbbbbbbbbbb2bbbbbbbbbbabbbbbbaaabbbbbbbbb222bbbbbabababbbb2b2b2bbb... 
... 

我想创建与所计数的独特字符的数目各样品的一个字典(或列表,熊猫数据帧)。也就是说,以字典形式:

sample_name1 = {'a': 1824600201, 'b': 2736900300, '2': 4561500501} 

为每一行。

在Python中统计字符的最快方法是使用from collections import Counter。可以将文本文件加载到numpy中,遍历矩阵的每一行,然后对每一行使用Counter()

但是,如何为每一行刮取正确的标签,特别是这些标签不是标准化的?也许我可以为每个矩阵行取第一个X字符?

+0

是你保证一个空格将标签与文本分开吗? – AChampion

+0

@AChampion是的,它看起来像一个标签。 – ShanZhengYang

+0

@尚正阳:连续有没有其他的空格字符? –

回答

1

假设数据的足够小的量,以适应​​(每行)的内存,那么你可以做简单的东西如:

results = {} 
with open('<myfile>') as f: 
    next(f) # skip first line 
    for line in f: 
     title, code = line.strip().split(' ') 
     results[title] = Counter(code) 

鉴于你的小例子集上面你:

{'sample_name1': Counter({'.': 3, '2': 21, 'a': 22, 'b': 25}), 
'sample_name2': Counter({'.': 3, '2': 7, 'a': 8, 'b': 53})} 
+0

对于我来说,上面的内容并不清楚你是如何在大文本文件中阅读的......(也就是说,这是python2.x,这没关系 - 这对其他SO读者来说意识到这一点很好) – ShanZhengYang

+0

固定的,我用'StringIO(str)'将字符串转换成文件接口,用'open('')替换文件。为什么你认为这是Python 2.x,我的默认环境是3.x? – AChampion

+0

我不认为在Python3.x中存在'StringIO()' – ShanZhengYang

1

我还没有测试过与您的数据差不多大小的任何东西,但您可以尝试如下所示。

前提是我们以块读取每行,并将ascii字符a, b, 2转换为整数,然后我们运行直方图。我们读大块的每一行的原因是因为每行都是90亿字节,这意味着这个文件在许多计算机上不适合内存。

首先让我们定义一些东西。 transtable是一个数组,它将采用a,b,2中的字符并将它们转换为0,1,2。我是这样写的,所以如果你有更多的角色可以推广。我们会将结果存储在形式为sample_name: np.array([a_count, b_count, 2_count])的字典hists中。

import numpy as np 

transtable = np.arange(256, dtype=np.uint8) 
transtable[np.frombuffer('ab2')] = np.arange(3) 

chunksize = 436549 # 9123001002/2/3^5/43 
invchunksize = 43*2*3**5 

hists = {} 
bins = np.arange(4) # 3 + 1 
# convenience function to take string buffer to counts of a,b,2 (0,1,2) 
hist_func = lambda buff: np.histogram(transtable[np.frombuffer(buff, np.uint8)], 
             bins=bins)[0] 

现在我们打开了该文件,并通过它解析头

with open(infile, 'r') as fin: 
    header_line = fin.readline() 
    rows, cols = map(int, header_line.split()) 

打开文件后,现在让我们来循环,首先得到样品名称

while True: 
     # parse name 
     name = '' 
     nextchar = '' 
     while nextchar != ' ': #may need to replace with '\t' 
      nextchar = fin.read(1) 
      name += nextchar 

现在,我们有样本名称,我们来解析实际数据:

 hist = np.zeros(3) 
     for _ in xrange(invchunksize): 
      dat = np.fromfile(fin, dtype=np.uint8, count=(chunksize)) 
      # stop reading if we didn't get chunksize bytes during last read 
      if data.size != chunksize: 
       break 

      hist += hist_func(dat) 

     hists[name] = hist 

     # read newline character and continue on to next line 
     fin.read(1)