Python—汇总文件中重复数据点的所有值

Python—汇总文件中重复数据点的所有值,python,python-2.7,file-io,Python,Python 2.7,File Io,假设我有一个.txt文件,如下所示: 1499371791 3145728 1499371791 4194304 1499371792 524288 1499371794 8912896 1499371794 3145728 1499371794 5242880 1499371795 3145728 1499371795 5242880 我希望能够将右列中与左列中相同值相关的所有值相加多次 例如,“14993717

假设我有一个.txt文件,如下所示:

    1499371791  3145728
    1499371791  4194304
    1499371792  524288
    1499371794  8912896
    1499371794  3145728
    1499371794  5242880
    1499371795  3145728
    1499371795  5242880
我希望能够将右列中与左列中相同值相关的所有值相加多次

例如,“1499371791”出现两次。我希望能够将右列中出现的两个“1499371791”值的总和写回文件。所以我想让它最后看起来像这样:

    1499371791  7340032  
    1499371792  524288
    1499371794  17301504
    1499371795  8388608
这样,左列中只有一个值与右列中的一个值相关

我不确定应该如何同时读取、汇总值和写入文件。我是否应该导入数据,然后将每个函数拆分?i、 e.分别读取、编辑和写入文件

我尝试使用“readlines()”来创建文件中的行列表。然后,我尝试使用该列表检查重复值,但返回的列表不是最佳格式,因此无法导航并随后进行编辑


如有任何建议,将不胜感激

您可以将txt文件读取为CSV,并将两列之间的空间定义为分隔符。比如:

import unicodecsv

# ...

with open(csvfile_entry, 'rb') as csvfile:
    spamreader = unicodecsv.reader(csvfile, delimiter=' ', quotechar='"', quoting=unicodecsv.QUOTE_MINIMAL)
    for row in spamreader:
        # you logic goes here

因此,这将读取整个文件,并将必要的行添加到变量中,如果下一个“键”是已处理行的一部分,则必须对值进行求和

您可以将txt文件读取为CSV,并将两列之间的空间定义为分隔符。比如:

import unicodecsv

# ...

with open(csvfile_entry, 'rb') as csvfile:
    spamreader = unicodecsv.reader(csvfile, delimiter=' ', quotechar='"', quoting=unicodecsv.QUOTE_MINIMAL)
    for row in spamreader:
        # you logic goes here
因此,这将读取整个文件,并将必要的行添加到变量中,如果下一个“键”是已处理行的一部分,则必须对值进行求和

python包“pandas”对这类操作最有帮助。请注意,在下面的示例中,文本文件不包含前导空格,列之间的间距正好是两倍。调整到您自己的文本文件规格,以获得最佳效果

import pandas as pd

df = pd.read_table("test.txt", header = None, sep='  ', engine='python')
df = df.set_index(0)
df = df.groupby(df.index).sum()
In [22]: df

Out[22]: 
                   1
0                   
1499371791   7340032
1499371792    524288
1499371794  17301504
1499371795   8388608
python包“pandas”对这类操作最有帮助。请注意,在下面的示例中,文本文件不包含前导空格,列之间的间距正好是两倍。调整到您自己的文本文件规格,以获得最佳效果

import pandas as pd

df = pd.read_table("test.txt", header = None, sep='  ', engine='python')
df = df.set_index(0)
df = df.groupby(df.index).sum()
In [22]: df

Out[22]: 
                   1
0                   
1499371791   7340032
1499371792    524288
1499371794  17301504
1499371795   8388608
试试这个:

from collections import defaultdict
with open('test.txt') as f:
    totals = defaultdict(int)
    for key, value in (map(int, line.strip().split('  ')) for line in f):
        totals[key] += value
    print('\n'.join(sorted(['  '.join(map(str, (key, totals[key]))) 
                            for key in totals])))

产出:

1499371791 7340032
1499371792 524288
1499371794 17301504
1499371795 8388608
试试这个:

from collections import defaultdict
with open('test.txt') as f:
    totals = defaultdict(int)
    for key, value in (map(int, line.strip().split('  ')) for line in f):
        totals[key] += value
    print('\n'.join(sorted(['  '.join(map(str, (key, totals[key]))) 
                            for key in totals])))

产出:

1499371791 7340032
1499371792 524288
1499371794 17301504
1499371795 8388608
使用字典 输出

将结果写入txt文件 您将有一个带有此输出的data3.txt文件

带函数的代码 我在使用函数和创建更复杂的东西方面做了一些更改

creadic-从文件data2.txt创建字典

请参见值-显示dict的值

writefile-接受2个参数,第一个是数据所在的文件,它们被求和,然后写入file2

控制台上的输出

文件2上的输出

在不同的步骤中选择数据 这是密码 输出 使用字典 输出

将结果写入txt文件 您将有一个带有此输出的data3.txt文件

带函数的代码 我在使用函数和创建更复杂的东西方面做了一些更改

creadic-从文件data2.txt创建字典

请参见值-显示dict的值

writefile-接受2个参数,第一个是数据所在的文件,它们被求和,然后写入file2

控制台上的输出

文件2上的输出

在不同的步骤中选择数据 这是密码 输出
你能解释一下你的意思吗(也举个例子)?将文件2中的输出按假设3的间隔分组的最佳方法是什么?例如,如果文件2上的输出为:1499371791 7340032 1499371792 524288 1499371794 17301504 1499371795 8388608 1499371797 8799002,并且我希望最终输出为:1499371791 7340032 1499371794 17301504 1499371797 8799002Ok,所以你想跳过一行。。。让我尝试一下,不必是一行,只需跳过左列3个间隔之间的所有内容。。因此,如果它从1499371791开始,则只保留偏移量为3倍数的数据值。比如1499371794,1499371797等等。。那么(写最后一个数字):1,4,7,10,13,16等等?你能解释一下你的意思吗,请(也举个例子)?把文件2中的输出分成3个间隔的最好方法是什么?例如,如果文件2上的输出为:1499371791 7340032 1499371792 524288 1499371794 17301504 1499371795 8388608 1499371797 8799002,并且我希望最终输出为:1499371791 7340032 1499371794 17301504 1499371797 8799002Ok,所以你想跳过一行。。。让我尝试一下,不必是一行,只需跳过左列3个间隔之间的所有内容。。因此,如果它从1499371791开始,则只保留偏移量为3倍数的数据值。比如1499371794,1499371797等等。。那么(写最后一个数字):1,4,7,10,13,16等等?你能告诉我为什么我在第5行得到“TypeError:“map”对象是不可下标的吗?@GiovanniGianni这是因为在python3
map
中对象不能被索引,所以尝试下标映射会出错。OP用
python-2.7
标记了这个问题,因此为什么我的答案在这种情况下是可以接受的。要使这个答案与python3兼容,你需要将
解析为
元组
列表
。我已经做了一个编辑,现在可以从地图中解包这些项目,以获得一个稍微优雅的答案,既
python2
python3
兼容,如果读者希望使用我的答案。好,很好,我很感激。你能告诉我为什么在第5行出现“TypeError:“map”对象不可下标吗?@GiovanniGianni这是因为在python3
map
中对象不能被索引,所以尝试
def creadic(datafile):
    'This creates the dictionary'
    kdic = {}
    with open(datafile, encoding='utf-8') as data:
        data = data.readlines()
        for d in data:
            d = d.rstrip(" ")
            d = d.split()
            try:
                kdic[d[0]] = int(d[1]) + int(kdic[d[0]])
            except KeyError:
                kdic[d[0]] = int(d[1])
    print("Dictionary created")
    return kdic

# dizio = creadic("data2.txt")
def seevalues(dic):
    'shows the values in the console'
    for k,v in dic.items():
        print(k,"\t",v)

def writefile(file1,file2):
    'sums the value in file1 and writes the summed ones in file2'
    kdic = creadic(file1)
    seevalues(kdic)
    with open(file2, "w",  encoding="utf-8") as data:
        for k,v in kdic.items():
            data.write(k + "\t" + str(v) + "\n")
    print("Data written")

writefile("data2.txt","data3.txt")
Dictionary created
1499371791   7340032
1499371792   524288
1499371794   17301504
1499371795   8388608
Data written
1499371791  7340032
1499371792  524288
1499371794  17301504
1499371795  8388608
"""
This are the data in data1.txt

1499371791  3145728
1499371791  4194304
1499371792  524288
1499371794  8912896
1499371794  3145728
1499371794  5242880
1499371795  3145728
1499371795  5242880
1499371797  3242880
1499371800  1242880
1499371800  2442880
1499371803  2442880
"""
def creadic(datafile):
    'This creates the dictionary'
    global start
    kdic = {}
    with open(datafile, encoding='utf-8') as data:
        data = data.readlines()

        for d in data:
            d = d.rstrip(" ")
            d = d.split()
            start = int(d[0].rstrip())
            try:
                kdic[d[0]] = int(d[1]) + int(kdic[d[0]])
            except KeyError:
                kdic[d[0]] = int(d[1])
    return kdic

# dizio = creadic("data2.txt")
def seevalues(dic):
    'shows the values in the console'
    for k,v in dic.items():
        print(k,"\t",v)

def writefile(file1,file2):
    'sums the value in file1 and writes the summed ones in file2'
    kdic = creadic(file1)
    seevalues(kdic)
    with open(file2, "w",  encoding="utf-8") as data:
        for k,v in kdic.items():
            data.write(k + "\t" + str(v) + "\n")
    print("Data written")

def writefile2(file1,file2,step):
    'sums the value in file1 and writes the summed ones in file2'
    global start
    kdic = creadic(file1)
    print("Data in console:")
    with open(file2, "w",  encoding="utf-8") as data:
        for k,v in kdic.items():
            if int(k)%(start+step)%3==0:
                data.write(k + "\t" + str(v) + "\n")
                print(k,v)
    print("This data has been written in {}".format(file2))

writefile2("data1.txt","data2.txt",3)
Data in console:
1499371800 3685760
1499371797 3242880
1499371791 7340032
1499371794 17301504
1499371803 2442880
This data has been written in data2.txt