Py学习  »  Python

如何使用Python计算大文件中每个数字的每次出现次数

Peter • 5 年前 • 2042 次点击  

我是Python的初学者,我想知道是否有人能帮我解决这个问题。

我有一个超过600万行的大文本文件,但每行只有一对“x,y”,x和y相对较小。

我要做的是,在Python中,计算我的文件中每出现一对“x,y”,并将它们写在一个excel文档中,每行表示de“y”,每列表示“x”。

我有一个有效的程序,但文件太大,它实际上需要一年多才能完成。

所以我想知道是否有一种更快的方法。

请记住,我在编程方面真的不是很好,因为我刚开始。

非常感谢潜在的答案。

这是我目前的代码:

import xlsxwriter

book = xlsxwriter.Workbook("MyCount.xlsx")

sheet1 = book.add_worksheet('Sheet 1')

sheet1.write(0,0,'y\x')

for i in range (0,1441):
    sheet1.write(0,i+1,i)

for i in range (1,118):
    sheet1.write(i,0,i)

file1=open("Data.txt","r")

count=0

for x in range (0, 1441):
    for y in range (1, 118):
        count=0
        number=f'{x}'+','+f'{y}'+'\n'
        for line in file1.readlines():
            if line == number:
                count+=1
        sheet1.write(y, x+1, count)
        file1.seek(0)

file1.close()
book.close()
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/51410
 
2042 次点击  
文章 [ 3 ]  |  最新文章 5 年前
satyam soni
Reply   •   1 楼
satyam soni    6 年前

我想这对你来说是更优雅的解决方案。将文件读入pandas数据框,按分组并计算对数。

import pandas as pd
d = [(1,2,3),(1,2,4),(1,2,1),(1,1,5),(1,4,5),(1,1,8)]

cntdt = pd.DataFrame(d,columns=['x','y','cnt'])
cntdt.head()

s = cntdt.groupby(['y','x']).size()

#to get the dataframe
s.to_frame('count').reset_index()

#to get the dictionary
s.to_dict()

字典输出:{(1,1):2,(2,1):3,(4,1):1} 数据帧输出:

<table border="1" class="dataframe"> <thead>   <tr style="text-align: right;">     <th></th>     <th>y</th>     <th>x</th>     <th>count</th>   </tr> </thead> <tbody>   <tr>     <th>0</th>     <td>1</td>     <td>1</td>     <td>2</td>   </tr>   <tr>     <th>1</th>     <td>2</td>     <td>1</td>     <td>3</td>   </tr>   <tr>     <th>2</th>     <td>4</td>     <td>1</td>     <td>1</td>   </tr> </tbody></table>
Alexandru Martin
Reply   •   2 楼
Alexandru Martin    6 年前

所以看看这个:

counts = {}

for line in open("data.txt", "r"):
    line = line.split(',')

    number_1 = None
    number_2 = None

    for line_element in line:

        try:
            number = int(line_element)
            if number_1 is None:
                number_1 = number
            else:
                number_2 = number
        except Exception:
            pass

    if number_1 and number_2:
        numbers_couple = '{},{}'.format(number_1, number_2)

        if numbers_couple in counts:
            counts[numbers_couple] += 1
        else:
            counts[numbers_couple] = 1

print(counts)

我的data.txt内容:

a,b,c,20,30,dad,glaas
fdls,cafd,erer,fdesf,2,4534
fdls,cafd,erer,fdesf,2,11

结果是:

{
   '20,30': 1, 
   '2,4534': 1, 
   '2,11': 1
}

您可以使用此结果将其写入您提到的新文件,方法是分割字典的键以获取x和y。

像这样,我已经计算了一个文件中的数对。这就是你要找的吗?请告诉我。

bruno desthuilliers
Reply   •   3 楼
bruno desthuilliers    6 年前

这是Alexandru解决方案的改进版(未经测试…)(注意:Alexandru发布自己的答案时,我已经在写了这个答案,但既然他先发布了,如果它有助于解决您的问题,请给他信用)。

一般的想法是只对文件执行一次单次扫描,而不是连续执行170038(=>1441*118)次顺序扫描,并减少 sheet.write() 调用找到的行数,而不是一遍又一遍地重写同一单元格。

此外,使用函数将有助于更快的执行,因为局部变量访问比全局变量访问更快。

不知道这是否能很快解决你的问题,但至少应该 许多的 比您当前的实现速度快。

注:6米 {(int,int):int} dict很容易放在大多数现代计算机的内存中(只是在我的内存中试过,我的内存已经很忙了),所以这不是问题(而且你已经在内存中读取了整个文件,这可能是更重的wrt/内存…)

from collections import defaultdict

def parse_file():
    counts = defaultdict(int)
    with open("Data.txt") as f:
        for lineno, line in enumerate(f):
            line = line.strip()
            if not line:
                continue
            try:
                xy = tuple(int(i) for i in line.split(","))
            except (TypeError, ValueError) as e:
                print("oops, line {} is broken ? (found '{}')".format(lineno, line))
                continue
            counts[xy] += 1
    return counts


def write_counts(counts):
    book = xlsxwriter.Workbook("MyCount.xlsx")
    sheet1 = book.add_worksheet('Sheet 1')
    sheet1.write(0,0,'y\x')
    for i in range (0,1441):
       sheet1.write(0,i+1,i)
    for i in range (1,118):
        sheet1.write(i,0,i)

    for (x, y), count in counts.items():
        sheet1.write(y, x+1, count)


def main():
    counts = parse_file()
    write_counts(counts)

if __name__ == "__main__":
    main()