Python - 从文件的第一列计算第二列

5
我是一名Python初学者,无法应对我的项目中的某些问题,希望您能帮助我:)
假设我有一个*.txt文件,只有一列数据,看起来像:
         Column-1

row-1    0
row-2    25.00
row-3    27.14
row-4    29.29
row-5    31.43
row-6    33.57

*在这里添加带行的列只是为了简化说明。

我需要计算第二列,它以第一列的输入数据为输入,并输出从前一个值中减去该行值的结果(如果行-1(列-1)值为0,则行-1(列-2)也应为0)。 它应该是这样的:

  • row-2(Column-2)= row-2(Column-1)- row-1(Column-1)
  • row-3(Column-2)= row-3(Column-1)- row-2(Column-1)等等。

让我展示一下输出文件应该是什么样子:

         Column-1  Column-2

row-1    0         0
row-2    25.00     25.00
row-3    27.14     2.14
row-4    29.29     2.15
row-5    31.50     2.21
row-6    33.57     2.07

目前我只在这里进行我的编程工作:

import sys

with open('file.txt', "r") as f:
    sys.stdout = open('%s (calc).txt' % f.name, 'a')
    for line in f:
        column = line.strip().split()
        Column_1 = float(column[0])
        column.extend([None])

我不知道接下来该怎么做,也许使用numpy可以解决这个问题?但是我并不擅长它(基本上完全不会),我应该学习它吗?

无论如何,非常感谢您的贡献。


看一下Pandas的rolling_apply函数:http://pandas.pydata.org/pandas-docs/stable/computation.html#moving-rolling-statistics-moments - asiviero
3个回答

5
我相信这会做你所要求的事情:
INPUT = 'file.txt'
OUTPUT = 'calc.txt'

def main():
    with open(INPUT, 'r') as reader, open(OUTPUT, 'a') as writer:
        last_value = 0
        for line in reader:
            column_1, *remaining_columns = map(float, line.split())
            column_2 = column_1 - last_value
            last_value = column_1
            print(column_1, column_2, sep='\t', file=writer)

if __name__ == '__main__':
    main()

你可以使用 column_1 = next(map(float, line.split())) 简化第8行。 - 301_Moved_Permanently
这是正确的,但它的写法会强制对其余列进行类型检查。采用你的方法,最好写成 column_1 = float(next(iter(line.split()))),因为不需要使用 map。目前第8行的写法将检查所有列是否为有效的浮点数值。 - Noctis Skytower
很好。但是OP使用float(line.split()[0]),这并没有表明其他列中包含的类型(如果有的话)。也许在所有地方都强制使用float并不能解决他们的输入问题。 - 301_Moved_Permanently
哇,谢谢您的快速回复,它真的有效:) 尽管对我来说理解整个过程有点困难,但我会尝试。 无论如何,它能够正常工作 - 再次感谢您) - Moveton
因此,编写 column_1 = float(line.split()[0]) 可能是最好的选择。我的示例旨在展示一些可能未知的可能性。如果代码和数据不符合相同的期望,它也将惨败。 - Noctis Skytower

2
一种方法是如下:假设你有两个列表:
a = [1,2,3,0]
b = [0,1,2,3]

您可以使用以下步骤从中减去一个列表来实现:

import operator
map(operator.sub, a, b)

为了实现这个目标,您需要将文件读入数组中(使用array.append(value)获取所有数据)。
然后复制数据,并将其偏移一位(列表长度需要相同)。如何处理数组的开头和结尾取决于这些值对您有多重要(也许您可以承受失去一个值)。

2

以下是使用列表推导式和zip的解决方案:

#!/usr/bin/env python3

with open('file.txt', "r") as f:

    # read column one into a list
    column_1 = [float(line.strip()) for line in f]
    # compute differences of neighbouring values
    column_2 = [now - last for now, last in zip(column_1, [0.0]+column_1[:-1])]

    with open("result.txt", "w") as outfile:
        for c1, c2 in zip(column_1, column_2):
            print("{:.2f}\t{:.2f}".format(c1, c2), file=outfile)

这里发生的事情是,我们首先从输入文件中创建所有条目的列表。使用zip,我们可以从两个(或更多)可迭代对象创建元组。我们必须创建第二个列表,将值向右移动1位,并在前面添加0.0作为第一个条目的哨兵。
现在,我们可以将这两个列表一起压缩,并使用第二个列表推导式计算值对之间的差异。
学习numpy总是一个好主意,但我认为对于这个任务来说会有些过度。

m00am,谢谢,我会尝试这个。 至于numpy - 感谢建议,稍后在更加熟悉“常见”事物后再去做 :) - Moveton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接