【问题标题】:Python - loop through a csv file row valuesPython - 循环通过 csv 文件行值
【发布时间】:2017-10-06 11:20:30
【问题描述】:

我有一个 csv 文件,如下所示 (test.csv),有两列。

338,800
338,550
339,670
340,600 
327,500
301,430
299,350
284,339
284,338
283,335
283,330
283,310
282,310
282,300
282,300
283,290

从第 1 列开始,我想读取当前行并将其与前一行的值进行比较。如果是greater OR equal,继续比较,如果当前单元格的值是smaller而不是前一行——那么我想要同一行中第二列的值。

接下来,我想将我们在第 1 列中得到的 larger value 除以第 2 列相同单元格中的值。让我说清楚。

例如在上面给出的表格中:根据我的要求,我们将从第 1 列得到的较小值是 327(因为 327 小于之前的值 340) - 然后我们取 500(这是对应的单元格值在第 2 列)。 最后我们将 340 除以 500 得到值 0.68。我的python 脚本应该在我们将值打印到控制台后立即退出。

目前,我在 bash 中使用以下脚本,它运行良好

awk -F, '$1<p && $2!=0{ 
val=$2/p    
if(val>=0.8 && val<=0.9)
    {
        print "A"
    }
else if(val==0.7)
    {
        print "B"
    }
else if(val>=0.5 && val <0.7)
    {
        print "C" 

    }
else if(val==0.5)
    {
        print "E"
    }
else
    {
        print "D" 
    }
exit
}
{ 
    p=$1 
}' test.csv

但我想用python 来做这件事,如果有任何帮助,我将不胜感激。这是我的方法

import csv

f = open("test.csv", "r+")
ff = csv.reader(f)

previous_line = ff.next()
while(True):
    try:
        current_line = ff.next()
        if previous_line <= current_line:
            print "smaller value"
    except StopIteration:
        break

【问题讨论】:

  • 你应该指定你期望得到的异常,这样如果你得到一个不同的异常,程序仍然会返回有用的信息:例如except StopIteration:
  • 哦,算了。好的,完成。

标签: python python-2.7 python-3.x csv


【解决方案1】:

我建议你使用csv.Reader 的内置迭代而不是直接调用.next()。而且您的代码不应测试正常浮点数的相等性。在任何语言中,这不仅仅是 Python 的事情。此外,0.79 的计算值将导致 D,这可能不是您想要的。

from __future__ import division
import csv

def category(val):
    if 0.8 < val <= 0.9:
        return "A"
    #Note: don't test val == 0.7: you should never test floats for equality
    if abs(val - 0.7) < 1e-10:
        return "B"
    if 0.5 < val < 0.7:
        return "C"
    if abs(val - 0.5) < 1e-10:
        return "E"
    return "D"

with open(r"E:\...\test.csv", "r") as csvfile:
    ff = csv.reader(csvfile)

    previous_value = 0
    for col1, col2 in ff:
        if not col1.isdigit():
            continue
        value = int(col1)
        if value >= previous_value:
            previous_value = value
            continue
        else:
            result = previous_value / int(col2)
            print category(result)
            break

编辑以响应对 OP 请求的更改

from __future__ import division
import csv

def category(val):
    if 0.8 < val <= 0.9:
        return "A"
    #Note: don't test val == 0.7: you should never test floats for equality
    if abs(val - 0.7) < 1e-10:
        return "B"
    if 0.5 < val < 0.7:
        return "C"
    if abs(val - 0.5) < 1e-10:
        return "E"
    return "D"

with open(r"E:\...\test.csv", "r") as csvfile:
    ff = csv.reader(csvfile)

    results = []
    previous_value = 0
    for col1, col2 in ff:
        if not col1.isdigit():
            continue
        value = int(col1)
        if value >= previous_value:
            previous_value = value
            continue
        else:
            result = previous_value / int(col2)
            results.append(result)
            print category(result)
            previous_value = value
    print (results)
    print (sum(results))
    print (category(sum(results) / len(results)))

我不得不猜测您要用于重置先前值的逻辑,因为您的原始值在第一个结果时出现了循环中断。而且我不知道您希望如何处理文件结尾。此修订版产生以下输出:

C
D
A
A
A
D
[0.68, 0.7604651162790698, 0.86, 0.8820058997050148, 0.8477611940298507, 0.9129032258064517]
4.94313543582
A

如您所见,results 中肯定有两个以上的值。

【讨论】:

  • 如果我们想要对结果求和或求平均值呢?我试过这样:sum_value = sum(result) 但我发现了以下错误:TypeError: 'float' object is not iterable
  • sum_value = sum(result) 不起作用,因为result 不是浮点数列表,它是单个值。它在每次迭代的for 循环中被新分配。为了做你想做的事,将result 的每个计算值存储在一个名为results 的列表中,然后在break 之前调用sum(results)
  • 每个 计算值存储在 results 中。 results=[result] 所做的是存储 last 计算值。你需要results.append(result),并且在你程序的早期,在循环之前,你需要将结果设置为一个空列表:results = [],否则你会得到一个NameError
  • category() 是将您的号码变成字母的功能。如果你只想要这个值,那么print ("Results:%.2f" %(sum(results) / len(results)))
  • @Brown 抱歉,我认为自己没有足够的经验来回答 numpy 的问题。
【解决方案2】:

如果它是与 pandas 一起使用的 .csv 文件,则可以为您提供更多控制权。

import numpy as np
import pandas as pd

pd.read_csv("filename.csv") # to read a .csv file into a dataframe

但是,对于这个例子,我没有使用 pd.read_csv() 函数。相反,我正在从 2D numpy 数组创建一个数据框,如下所示,

dataframe = pd.DataFrame(np.array([[338,800],
    [338,550],
    [339,670],
    [340,600], 
    [327,500],
    [301,430],
    [299,350],
    [284,339],
    [284,338],
    [283,335],
    [283,330],
    [283,310],
    [282,310],
    [282,300],
    [282,300],
    [283,290]]))

现在我有了一个数据框对象,我可以像在 python 中的其他对象类型一样操作它。我可以调用 pandas 特定的函数来处理我想要的结果的数据框。

def compare_and_divide(df):
    for i in range(len(df)-1):
        # df[0] for all values in col 0 .iloc[i] for value in row
        if df[0].iloc[i+1] >= df[0].iloc[i]:                                 
            continue     
        else:
            df[0].iloc[i+1] = df[0].iloc[i]

    return df[0].div(df[1]) # .div() function to divide values in col 0 by col 1

compare_and_divide(dataframe)   

0     0.422500
1     0.614545
2     0.505970
3     0.566667
4     0.680000 # 340/500 value mentioned in the question
5     0.790698
6     0.971429
7     1.002950
8     1.005917
9     1.014925
10    1.030303
11    1.096774
12    1.096774
13    1.133333
14    1.133333
15    1.172414
dtype: float64

【讨论】:

    【解决方案3】:
    col_1 = []
    col_2 = []
    with open("test.csv", "r+") as f:
        for elem in f.readlines():
            col_1.append(float(elem.split(",")[0]))
            col_2.append(float(elem.split(",")[1]))
    
    condition = True
    i=0
    while condition:
        if (col_1[i+1]-col_1[i]<0):
            print col_1[i]/col_2[i+1]
            condition = False
        i+=1
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-10-06
      • 1970-01-01
      • 1970-01-01
      • 2017-03-25
      • 2016-07-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多