Python - 在CSV文件中为每一列计算平均值

4

我是Python的新手,正在尝试计算csv文件中每一列或每一行的平均值,然后选择高于其列(或行)平均值两倍的值。我的文件有数百列,并且包含如下所示的浮点值:

845.123,452.234,653.23,...
432.123,213.452.421.532,...
743.234,532,432.423,...

我尝试了几种方法对代码进行更改,以便为每一列获取平均值(分别计算),但目前我的代码如下:

def AverageColumn (c):
    f=open(csv,"r")
    average=0
    Sum=0
    column=len(f)
    for i in range(0,column):
        for n in i.split(','):
            n=float(n)
            Sum += n
        average = Sum / len(column)
    return 'The average is:', average

    f.close()


csv="MDT25.csv"
print AverageColumn(csv)

但是我总是会收到类似“f没有len()”或“'int'对象不可迭代”的错误...
如果有人能向我展示如何获取每列(或行,根据您的需要)的平均值,然后选择大于其列(或行)平均值的两倍的值,我将非常感激。我宁愿不使用导入csv模块,但这取决于您的喜好。谢谢!

为什么你不想使用stdlib模块(例如csv)? - Adam Smith
1
@AdamSmith:模块将解决问题。不使用模块将教会如何编码。 - Amadan
1
@Amadan 我从来没有理解过那种观点。如果你真的相信这一点,你可能不会认为任何解释性语言是“编码”,可能会要求自己构建编译器,或者直接编写机器代码。 - Adam Smith
@AdamSmith:草人论点。要学习Python的基础知识,你应该亲自动手写Python的基础内容。一个库不会教你如何在return之后不再编写代码,也不会教你如何使用数组同时进行多个计算。 - Amadan
7个回答

5
这里是您的函数的清理版,但它可能并不能达到您想要的效果。 目前,它正在获取所有列中所有值的平均值:
def average_column (csv):
    f = open(csv,"r")
    average = 0
    Sum = 0
    row_count = 0
    for row in f:
        for column in row.split(','):
            n=float(column)
            Sum += n
        row_count += 1
    average = Sum / len(column)
    f.close()
    return 'The average is:', average

我会使用 csv 模块(使 csv 解析更加容易),结合 Counter 对象来管理列的总数,以及一个 上下文管理器 来打开文件(不需要使用 close()):

import csv
from collections import Counter

def average_column (csv_filepath):
    column_totals = Counter()
    with open(csv_filepath,"rb") as f:
        reader = csv.reader(f)
        row_count = 0.0
        for row in reader:
            for column_idx, column_value in enumerate(row):
                try:
                    n = float(column_value)
                    column_totals[column_idx] += n
                except ValueError:
                    print "Error -- ({}) Column({}) could not be converted to float!".format(column_value, column_idx)                    
            row_count += 1.0            

    # row_count is now 1 too many so decrement it back down
    row_count -= 1.0

    # make sure column index keys are in order
    column_indexes = column_totals.keys()
    column_indexes.sort()

    # calculate per column averages using a list comprehension
    averages = [column_totals[idx]/row_count for idx in column_indexes]
    return averages

3

首先,就像人们所说的那样 - CSV格式看起来很简单,但一旦涉及到字符串,它可能会变得相当复杂。monkut已经为您提供了两种解决方案,即整理过的代码版本和使用CSV库的另一种方案。我将提供另一个选项:不使用库,但有大量惯用代码可以借鉴,这将为您同时提供所有列的平均值。

def get_averages(csv):
    column_sums = None
    with open(csv) as file:
        lines = file.readlines()
        rows_of_numbers = [map(float, line.split(',')) for line in lines]
        sums = map(sum, zip(*rows_of_numbers))
        averages = [sum_item / len(lines) for sum_item in sums]
        return averages

需要翻译的内容如下:

需要注意的是,在您的代码中,f 是一个文件对象。您尝试在返回值之后关闭它。除非您使用了 try...finally 结构或 with 结构(就像我正在使用的那样 - 它将自动关闭流),否则在处理完 return 后不会执行任何内容。

map(f, l) 或等效的 [f(x) for x in l],创建一个新列表,其元素是通过在 l 上的每个元素上应用函数 f 而获得的。

f(*l) 将在函数调用之前“解包”列表 l,并将每个元素作为单独的参数传递给函数 f


谢谢,我很感激,但是我遇到了这个错误: rows_of_numbers = [map(float, line.split(',')) for line in lines] ValueError: 无法将字符串转换为浮点数: - Pabloo LR
好的,我找到了错误,是因为最后一列不同。 - Pabloo LR

1

这对我来说绝对有效!

import numpy as np
import csv

readdata = csv.reader(open('C:\\...\\your_file_name.csv', 'r'))
data = []

for row in readdata:
  data.append(row)

#incase you have a header/title in the first row of your csv file, do the next line else skip it
data.pop(0) 

q1 = []  

for i in range(len(data)):
  q1.append(int(data[i][your_column_number]))

print ('Mean of your_column_number :            ', (np.mean(q1)))

1
最好告诉楼主为什么这对你有效。 - cmprogram
很简单,我的CSV文件有5列,第一行包含列的标题。最初我读取了CSV文件,将每一行存储到一个numpy数组(data [])中,然后弹出了包含标题(非数字值)的第一行,以避免在计算平均值时出错。我使用numpy包的内置平均函数,从中获取所需列的新numpy数组(q1 []),并计算平均值。 - Sahana M

0

希望这能对你有所帮助......一些帮助......这是我会做的 - 使用numpy:

    # ==========================
    import numpy as np
    import csv as csv

    #  Assume that you have 2 columns and a header-row: The Columns are (1) 
    #  question # ...1; (2) question 2
    # ========================================

    readdata = csv.reader(open('filename.csv', 'r'))  #this is the file you 
    # ....will write your original file to....============
    data = []
    for row in readdata:
    data.append(row)
    Header = data[0]
    data.pop(0)
    q1 = []
    q2 = []
    # ========================================

    for i in range(len(data)):
        q1.append(int(data[i][1]))
        q2.append(int(data[i][2]))
    # ========================================
    # ========================================
    # === Means/Variance - Work-up Section ===
    # ========================================
    print ('Mean - Question-1:            ', (np.mean(q1)))
    print ('Variance,Question-1:          ', (np.var(q1)))
    print ('==============================================')
    print ('Mean - Question-2:            ', (np.mean(q2)))
    print ('Variance,Question-2:          ', (np.var(q2)))

0
import csv
from statistics import mean
with open(r'path/to/csv','r') as f:
    reader = csv.reader(f)
    print(mean([float(i[2]) for i in reader if i[2].isnumeric()]))

将“2”替换为您希望计算的列的索引


0
如果出于某种原因你不想使用stdlib模块,那么可以这样做:
with open('path/to/csv') as infile:
    columns = list(map(float,next(infile).split(',')))
    for how_many_entries, line in enumerate(infile,start=2):
        for (idx,running_avg), new_data in zip(enumerate(columns), line.split(',')):
            columns[idx] += (float(new_data) - running_avg)/how_many_entries

0

我建议将此分解为几个较小的步骤:

  1. 将CSV文件读入2D列表或2D数组中。
  2. 计算每列的平均值。

这些步骤中的每一个都可以作为两个单独的函数实现。(在实际情况下,如果CSV文件很大,将整个文件读入内存可能会受到空间限制的限制。但是,对于学习练习来说,这是了解编写自己的函数的好方法。)


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