【问题标题】:Is there a way evaluate two cases at the same time with a greater then and a less than in python?有没有办法在python中同时评估两个案例,一个大于一个,一个小于一个?
【发布时间】:2013-08-06 16:20:47
【问题描述】:

我正在尝试对包含 21 列和很多行的数据集进行分类。我已经到了可以将数据导入为 csv 并打印出单独的列的地步。我还有两件事要做。首先,我希望能够打印出特定的数据点。例如,位于第 2 行第 4 列的数据点。第二个任务是根据第 4 列和第 5 列对数据行进行分类。这些列是纬度和经度。我正在尝试获取位于世界特定区域的行。所以我的想法是这样的

if  60 > row[4] > 45 and 165 > row[1] > 150:

ie(就像数学运算 (9 > x > 5))

我不确定执行上述过程的正确方法是什么。

我已将代码粘贴到底部。我是python编程的新手,所以请随时指出错误。

import csv
path = r'C:\Documents and Settings\eag29278\My Documents\python test code\test_satdata.csv'
with open(path, 'rb') as f:
    reader = csv.reader(f, delimiter=',')
    for row in reader:
        print row [0]
        #this prints out the first column 

    var1 = []

    for row in f:

       if  60 > row[4] > 45 and 165 > row[1] > 150:

          var1.append(row)

print var1

更新 1

好的,所以我更新了代码,但是当我运行模块时,我得到了这个输出..

2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 2010 []

所以我看到程序打印出 var1 但它是空的

【问题讨论】:

  • 9 > x > 5 在 python 中工作正常。
  • 看起来你的代码应该完全按照你想要的那样做。所以……你有问题吗?如果您只想查看工作代码,请使用 Code Review,而不是 Stack Overflow。
  • 我猜代码审查是专门用于故障排除的网站?
  • for row in f 将为每一行生成一个 str 对象,这就是为什么没有附加任何行的原因。 60 > 'foo' > 45 在 Python 中不会引发异常——它只会返回 False。
  • @erik.garcia294 不,CodeReview 适用于你有工作代码,但你认为它可以写得更干净或运行得更快的时候。

标签: python csv classification


【解决方案1】:

来自docs

比较可以任意链接,例如,x < y <= z 是等价的 到x < yy <= z,除了y 只被评估一次(但在这两个 当发现x < y 为假时,根本不会评估z)。

【讨论】:

  • 这个答案虽然肯定提供了正确的信息,但对解决 OP 的真正问题没有任何帮助。
【解决方案2】:

所有关于“链式比较”的答案(例如60 > foo > 45)完全没有抓住重点。链式比较没有问题。但是您的代码中有很多问题。

首先,CSV 阅读器返回的行总是将字符串作为元素。所以如果 CSV 看起来像

10,20,abc,40

当您使用 CSV 阅读器时,Python 中的结果是

['10', '20', 'abc', '40']  # list of strings

在 Python 2 中,将字符串与数字进行比较是“可行的”,因为您可以这样做,并且不会引发任何异常。但这通常不是你想要的。例如:

Python 2.7.3 (default, Apr 10 2012, 23:24:47) [MSC v.1500 64 bit (AMD64)] on win
32
Type "help", "copyright", "credits" or "license" for more information.
>>> 1 < '2'
True
>>> 2 < '1'
True

请注意,Python 3 甚至不允许您将字符串与数字进行比较:

Python 3.2.3 (default, Apr 11 2012, 07:12:16) [MSC v.1500 64 bit (AMD64)] on win
32
Type "help", "copyright", "credits" or "license" for more information.
>>> 1 < '2'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unorderable types: int() < str()
>>>

因此,您需要做的一件事是将 CSV 中的字符串转换为整数:

>>> 1 < '2' < 3  # Python 2
False
>>> 1 < int('2') < 3
True

您需要做的另一件事是确保您正在读取 CSV 行,而不是文件中的普通旧行。你在哪里

var1 = []
for row in f:
   if  60 > row[4] > 45 and 165 > row[1] > 150:
      var1.append(row)

您正在做的是将每行的第 5 个 字符 与 60 和 45 进行比较,并将每行的第 2 个 字符 与 165 和 150 进行比较。您几乎肯定是说

var1 = []
for row in reader:
    if 60 > int(row[4]) > 45 and 165 > int(row[1]) > 150:
        var1.append(row)

但不幸的是,这还不是全部。当您这样做时,您已经“用完”了 CSV 中的所有行

for row in reader:
    print row [0]

在该循环结束时,reader 没有更多行可读取。最直接的做法是重新打开文件并为每个循环使用新的阅读器:

with open(path, 'rb') as f:
    reader = csv.reader(f, delimiter=',')  # why specify the delimiter?
    for row in reader:
        print row[0]
        #this prints out the first column 

with open(path, 'rb') as f:  # we open the file a second time
    reader = csv.reader(f)
    var1 = []
    for row in f:
        if 60 > int(row[4]) > 45 and 165 > int(row[1]) > 150:
            var1.append(row)

对于初学者,甚至是最有经验的 Python 程序员来说,这已经足够了。代码清晰到显而易见,这通常是一件好事。如果特殊情况要求采取更好的措施,请查看这些过去的问题以寻找可能的替代方案:

Can iterators be reset in Python?

Proper way to reset csv.reader for multiple iterations?

【讨论】:

  • 首先感谢您花时间帮助我。我确实对您推荐的内容感到满意,但是在执行代码 Traceback(最近一次调用最后一次)的大约一半时间里,我收到了这个错误:文件“C:\Python27\test code\12345.py”,第 9 行,在 if 60 > int(row[3]) > 45 and 165 > int(row[4]) > 150: ValueError: invalid literal for int() with base 10: '8.67' 1 其余时间我收到一个空变量当我打印时
  • 好吧,希望你明白int 是用来转换成整数的。您可能应该改用float。当您阅读人们的答案时,您真的应该尝试理解他们在说什么,而不仅仅是盲目地输入他们的代码。如果您不明白,请尝试在文档中查找内容。或者使用谷歌。通过付出努力,您不仅会学到更多知识,其他人也更有可能愿意帮助您。人们通常不想为您完成所有工作。人们绝对不想为你做你所有的想法
【解决方案3】:

这一行:

if  60 > row[4] > 45 and 165 > row[1] > 150:

正在比较60 &gt; [the fifth character in the row, as a string] &gt; 45 ...。我猜这不是你想要的。 for row in f 为文件中的每一行生成一个字符串。我认为您打算在进行这些比较之前进行一些解析。或者,也许您想迭代 reader 而不是 ff 是文件本身,而不是 csv 阅读器。

这应该会更好:

with open(path, 'rb') as f:
    reader = csv.reader(f, delimiter=',')
    var1 = [] # This is a very poorly named variable, by the way.
    for row in reader:
        print row [0]
        if  60 > row[4] > 45 and 165 > row[1] > 150:
            var1.append(row)

【讨论】:

  • 我现在知道我不应该使用 f,是否有替代方案可以产生可以给我输出的东西...有人建议在阅读器中使用这一行作为行,但我仍然得到相同的输出。更多解析是什么意思?
  • 在这种情况下,解析意味着将字符串强制转换为 int。如果您正在遍历 csv 阅读器,您可能需要执行类似 int(row[4]) 的操作,或者如果您正在遍历 f,您可能需要执行类似 int(line.split(',')[4]) 的操作。
  • 嗯。好吧,您指出了几个问题:(1) CSV 元素始终是字符串,(2) 字符串不一定以有用或直观的方式与整数进行比较,以及 (3) OP 似乎对文件之间的区别感到困惑以及该文件的 CSV 阅读器。但是你的代码 sn-p 不能修复 (1) 或 (2)。
【解决方案4】:

这实际上在 Python 中可以正常工作。大多数其他语言不会让你这样做。你必须写60 &gt; row[4] and row[4] &gt; 45 and ...

【讨论】:

  • @JonClements:稍微改变了措辞。
【解决方案5】:

您通常会使用&lt; 来编写它,使其看起来更像BETWEEN 操作...

if  (45 < row[4] < 65) and (150 < row[1] < 165):

【讨论】:

    【解决方案6】:

    链接也适用于其他运算符,例如==isin。有一个隐含的and

    你可以在这里使用列表推导

    var1 = [row for row in f if 45 < row[4] < 60 and 150 < row[1] < 165]
    

    我同意@Jon。使用&lt;&gt; 读起来更自然

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-03-18
      • 2019-06-09
      • 1970-01-01
      • 2020-09-06
      • 2020-06-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多