2

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

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

即(就像数学运算(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 []

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

4

6 回答 6

5

文档

比较可以任意链接,例如,x < y <= z等价于x < yand y <= z,除了y只评估一次(但在这两种情况下,当发现为假z时根本不评估)。x < y

于 2013-08-05T20:23:36.403 回答
1

这一行:

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

正在比较60 > [the fifth character in the row, as a string] > 45 ...。我猜这不是你想要的。for row in f为文件中的每一行生成一个字符串。我认为您打算在进行这些比较之前进行一些解析。或者,也许您想迭代reader而不是f. f是文件本身,而不是 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)
于 2013-08-05T22:21:37.053 回答
1

所有关于“链式比较”的答案(例如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 程序员来说,这已经足够了。代码清晰到显而易见,这通常是一件好事。如果特殊情况要求采取更好的措施,请查看这些过去的问题以寻找可能的替代方案:

可以在 Python 中重置迭代器吗?

为多次迭代重置 csv.reader 的正确方法?

于 2013-08-06T07:12:44.897 回答
0

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

于 2013-08-05T20:21:49.710 回答
0

您通常会使用它来编写它<,使其看起来更像是一个BETWEEN操作......

if  (45 < row[4] < 65) and (150 < row[1] < 165):
于 2013-08-05T20:21:52.147 回答
0

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

你可以在这里使用列表理解

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

我同意@Jon。对我来说,使用阅读比使用<阅读更自然>

于 2013-08-05T20:28:41.613 回答