【问题标题】:Calculating the mean across multiple files计算多个文件的平均值
【发布时间】:2013-07-19 03:05:37
【问题描述】:

我对 Python 很陌生,我也搜索了很多东西以找到与我类似的问题。我想做类似这个问题中解释的事情 Computing averages of records from multiple files with python

但是,我不想取每个值的平均值(如本例中所有值都是数字),我想取单个列的平均值,但其他列的值保持相同”

例如:

fileA.txt:  
0.003 0.0003 3 Active   
0.003 0.0004 1 Active  

fileB.txt:  
0.003 0.0003 1 Active   
0.003 0.0004 5 Active  

我想生成以下输出文件

output.txt
0.003 0.0003 2 Active   
0.003 0.0004 3 Active

虽然第 1 列和第 2 列也是数字,但对于 100 个文件的相同位置,它们将是相同的值。所以我只对第 3 列的 100 个文件中每个元素的平均值感兴趣。

此外,尽管问题Computing averages of records from multiple files with python 中的代码可用于读取我的文件。如果您有很多文件,它就没有用。我该如何优化呢?

我设法使用以下代码读取我的文件:

import numpy as np

result = []
for i in my_files:
    a = np.array(np.loadtxt(i, dtype = str, delimiter = '\t', skiprows = 1))
    result.append(a)
result = np.array(result)

我使用了这个问题initialize a numpy array中建议的类似代码

我的每个文件每 4 列大约有 1500 行。我尝试使用 np.mean 但它不起作用可能是因为我的某些数据是字符串类型。

提前感谢您的帮助!

【问题讨论】:

  • 要确保所有元素都是数字,请尝试使用地图,例如allDouble = map( lambda el : float(el), mixedTypeArray )。另外,如果您希望它们是数字,请不要将 dtype 设置为 str。
  • 谢谢!如果我没有将 dtype 设置为 str,我会收到以下错误消息:ValueError: could not convert string to float: Transposon Inactive。我如何使用这个地图功能...我不明白你的意思(对不起)。
  • 你需要第四列吗?如果没有在下面看到我的答案。 map 是一个有用的函数,它允许您将函数应用于数组的每个成员。 lambda 在 map 函数中定义了一个函数。相当于def toFloat(num): float(num); map( toFloat, arrayToBeConverted)。这需要一些时间来适应,但一旦你习惯了就会非常有用。
  • 是的,我确实需要第四列。最后我会画一个图表。不过谢谢你的回答。
  • 当然。您可以单独为该列调用 np.loadtxt,即 activeCol = np.loadtxt(i, dtype=str, usecols = (4), ... )

标签: python arrays numpy mean


【解决方案1】:

如果您使用np.genfromtxt(..., dtype=None) 加载数组,那么genfromtxt 将猜测每列的dtype。例如,第三列将被赋予一个整数 dtype。这将使您的数组适合算术。使用dtype='str'会产生一个字符串数组,不适合算术。


import csv
import numpy as np
import itertools as IT
my_files = ['fileA.txt', 'fileB.txt']

vals = None
for num, filename in enumerate(my_files, 1):
    arr = np.genfromtxt(filename, dtype=None, delimiter='\t', skiprows=1, usecols=(2,))
    print(arr)
    if vals is None:
        vals = arr
    else:
        vals += arr

meanvals = vals / num

with open(my_files[0], 'rb') as fin, open('/tmp/test.csv', 'wb') as fout:
    # skip first row
    next(fin)
    writer = csv.writer(fout, delimiter='\t', lineterminator='\n')
    for row, val in IT.izip(csv.reader(fin, delimiter='\t'), meanvals):
        row[2] = val
        writer.writerow(row)

/tmp/test.csv 中的结果如下所示:

0.003   0.0003  2   Active
0.003   0.0004  3   Active

【讨论】:

  • 谢谢!我尝试了您的代码并收到以下错误消息 IndexError: too many indices。我不知道它可能是什么。有什么建议吗?
  • 是的,有一个错误。 np.genfromtxt 返回一个结构化数组,它是一维的,不是二维的。所以你会得到第三列arr['f2'],而不是arr[:, 2]。 (列或字段名称默认为标签f0f1 等。)。
  • 谢谢!现在它确实奏效了。我还使用 np.mean 尝试了这个版本,它也可以工作。我不知道这个'f1'等 :) 所以如果我想写所有其他列的信息,我应该只在一个文件中循环一次,然后在另一个 txt 文件中复制第 1、2 和 4 列的信息并将这个平均变量“meanvals”添加为第三列?不知道该怎么做,但我会试着弄清楚! :)
  • 对不起,当我阅读您的答案时,它没有显示完整的代码!再次感谢!!那非常有用!我将尝试使用我的完整数据而不是两行数据集! :)
  • 我还有一个问题...如何保存 .csv 文件但保持数字不变?例如...第一个数字是 0.003,当我执行此代码时,它会保存一个数字为 0.0029999999999999997 的 csv 文件。有没有办法在保存之前将整个数组转换为字符串?谢谢!
【解决方案2】:

np.loadtxt 中还有另一个关键字 arg:usecols。尝试使用它,例如

a = np.loadtxt(i, usecols = (0,1,2), delimiter = '\t', skiprows = 1)

你不需要 np.array,因为 np.importtxt 返回一个 ndarray。我省略了 dtype=str,因为默认值是 dtype=float,如果你想计算平均值,这对你应该没问题。

另外,如果您只想计算每个文件中的平均值,而不是创建一个数组数组,我建议您在 for 循环中执行此操作并保存该计算的结果。

【讨论】:

    猜你喜欢
    • 2017-02-06
    • 2019-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-12
    • 1970-01-01
    • 2014-05-30
    • 1970-01-01
    相关资源
    最近更新 更多