为什么不返回CSV文件列的平均值?

时间:2013-05-01 04:01:18

标签: python

def averager(filename):
    f=open(filename, "r")
    avg=f.readlines()
    f.close()
    avgr=[]
    final=""
    x=0
    i=0
    while i < range(len(avg[0])):
        while x < range(len(avg)):
            avgr+=str((avg[x[i]]))
            x+=1
        final+=str((sum(avgr)/(len(avgr))))
        clear(avgr)
        i+=1
    return final

我得到的错误是:

File "C:\Users\konrad\Desktop\exp\trail3.py", line 11, in averager
    avgr+=str((avg[x[i]]))
TypeError: 'int' object has no attribute '__getitem__'

5 个答案:

答案 0 :(得分:2)

x只是一个整数,因此您无法将其编入索引。

所以,这个:

x[i]

永远不应该工作。这就是错误所抱怨的。

<强>更新

由于您要求提供有关如何简化代码的建议(在下面的评论中),所以请点击:

假设您的CSV文件类似于:

-9,2,12,90...
1423,1,51,-12...
...

您可以像这样阅读文件:

with open(<filename>, 'r') as file_reader:
    file_lines = file_reader.read().split('\n')

请注意,我使用了.split('\n')。这会导致文件的内容存储在file_lines中,因为它是文件中的行列表。

因此,假设您想要对i列进行求和,可以通过理解轻松完成:

ith_col_sum = sum(float(line.split(',')[i]) for line in file_lines if line)

那么为了平均一切,你可以将总和除以行数:

average = ith_col_sum / len(file_lines)

答案 1 :(得分:1)

其他人指出了错误的根本原因。以下是编写方法的不同方法:

def csv_average(filename, column):
    """ Returns the average of the values in
        column for the csv file """

    column_values = []

    with open(filename) as f:
        reader = csv.reader(f)
        for row in reader:
            column_values.append(row[column])

    return sum(column_values) / len(column_values)

答案 2 :(得分:0)

让我们来看看这段代码:

def averager(filename):

averager作为名称并不尽如人意。例如averagecsv怎么样?

    f=open(filename, "r")
    avg=f.readlines()

avg命名不佳。这不是一切的平均值!这是一堆线。例如,将其称为csvlines

    f.close()
    avgr=[]

avgr命名不佳。它是什么?名字应该是有意义的,否则为什么要给他们?

    final=""
    x=0
    i=0
    while i < range(len(avg[0])):
        while x < range(len(avg)):

如评论中所述,您可以将这些替换为for循环,如for i in range(len(avg[0])):中所示。这使您无需声明和增加有问题的变量。

            avgr+=str((avg[x[i]]))

咦?让我们打破这一行。

命名不佳的avg是来自csv文件的行。

所以,我们用x索引avg,好吧,这会给我们提供行号x。但是...... x [i]没有意义,因为x是一个整数,而整数不支持数组访问。我想你在这里要做的是......将文件分成行,然后将行分成列,因为它是csv。正确?

所以让我们放弃代码。你想要这样的东西,使用split http://docs.python.org/2/library/stdtypes.html#str.split函数:

totalaverage = 0
for col in range(len(csvlines[0].split(","))):
    average = 0
    for row in range(len(csvlines)):
        average += int(csvlines[row].split(",")[col])
    totalaverage += average/len(csvlines)
return totalaverage

等等!还有更多! Python有一个内置的csv解析器比分割,更安全。请在此处查看:http://docs.python.org/2/library/csv.html

答案 3 :(得分:0)

在回应OP询问他应该如何在其中一条评论中提及这一点时,我的建议如下:

import csv
from collections import defaultdict    
with open('numcsv.csv') as f:
    reader = csv.reader(f)
    numbers = defaultdict(list) #used to avoid so each column starts with a list we can append to
    for row in reader:
        for column, value in enumerate(row,start=1):
            numbers[column].append(float(value)) #convert the value to a float 1. as the number may be a float and 2. when we calc average we need to force float division
    #simple comprehension to print the averages: %d = integer, %f = float. items() goes over key,value pairs
    print('\n'.join(["Column %d had average of: %f" % (i,sum(column)/(len(column))) for i,column in numbers.items()]))

>>> 
Column 1 had average of: 2.400000
Column 2 had average of: 2.000000
Column 3 had average of: 1.800000

对于文件:

1,2,3
1,2,3
3,2,1
3,2,1
4,2,1

答案 4 :(得分:0)

这是两种方法。第一个只是获得该行的平均值(上面的代码看起来像是在做什么)。第二个得到一列的平均值(这是你提出的问题)

''' This just gets the avg for a line'''
def averager(filename):
  f=open(filename, "r")
  avg = f.readlines()
  f.close()

  count = 0
  for i in xrange(len(avg)):
    count += len(avg[i])

  return count/len(avg)

''' This gets a the avg for all "columns"
char is what we split on , ; | (etc)
'''
def averager2(filename, char):
  f=open(filename, "r")
  avg = f.readlines()
  f.close()

  count = 0 # count of items
  total = 0 # sum of all the lengths
  for i in xrange(len(avg)):
    cols = avg[i].split(char)
    count += len(cols)
    for j in xrange(len(cols)):
      total += len(cols[j].strip()) # Remove line endings

  return total/float(count)