使用Python在一列中选择具有特定值范围的行

Bra*_*don 4 python parsing loops rows

我知道这很简单,但我是Python的新用户,所以我在这里遇到了一些麻烦.我顺便使用Python 3.

我有多个文件看起来像这样:

NAME DATE AGE SEX COLOR

Name Date Age Sex Color
Ray  May  25.1 M  Gray
Alex Apr  22.3 F  Green
Ann  Jun  15.7 F  Blue
Run Code Online (Sandbox Code Playgroud)

(假设这是制表符分隔.我应该补充一点,真正的文件将有大约3,000行和17-18列)

我想要做的是选择年龄列中小于23的值的所有行.

在此示例中,输出将是:

Name Date Age Sex Color
Alex Apr  22.3 F  Green
Ann  Jun  15.7 F  Blue
Run Code Online (Sandbox Code Playgroud)

这是我试图做的事情:

f = open("addressbook1.txt",'r')
line = f.readlines()
file_data =[line.split("\t")]
f.close()

for name, date, age, sex, color in file_data:
    if age in line_data < 23:
        g = open("college_age.txt",'a')
        g.write(line)
    else:
        h = open("adult_age.txt",'a')
        h.write(line)
Run Code Online (Sandbox Code Playgroud)

现在,理想情况下,我有20-30个这样的"地址簿"输入文件,我希望这个脚本循环遍历它们,并将年龄低于23的所有条目添加到同一个输出文件("college_age.txt").我真的不需要保留其他线路,但我不知道还能用它们做什么.

当我运行它时,该脚本会生成错误.

AttributeError: 'list' object has no attribute 'split'
Run Code Online (Sandbox Code Playgroud)

然后我将第三行更改为:

file_data=[line.split("\t") for line in f.readlines()]
Run Code Online (Sandbox Code Playgroud)

它不再给我一个错误,但根本什么都不做.它刚刚开始然后开始.

有帮助吗?:)记住我对Python很愚蠢.

我应该补充一点,我的实际数据有小数而不是整数.我编辑了上面的数据来反映这一点.

Gar*_*tty 5

这里的问题是你使用了readlines()两次,这意味着第一次读取数据,然后第二次没有任何东西.

您可以直接在文件上迭代而不使用readlines()- 事实上,这是更好的方法,因为它不会立即读取整个文件.

虽然您可以按照自己的意愿执行您要执行的操作str.split(),但更好的选择是使用专为此任务设计csv模块.

import csv

with open("addressbook1.txt") as input, open("college_age.txt", "w") as college, open("adult_age.txt", "w") as adult:
   reader = csv.DictReader(input, dialect="excel-tab")
   fieldnames = reader.fieldnames
   writer_college = csv.DictWriter(college, fieldnames, dialect="excel-tab")
   writer_adult = csv.DictWriter(adult, fieldnames, dialect="excel-tab")
   writer_college.writeheader()
   writer_adult.writeheader()
   for row in reader:
       if int(row["Age"]) < 23:
          writer_college.writerow(row)
       else:
          writer_adult.writerow(row)
Run Code Online (Sandbox Code Playgroud)

那我们在这做什么呢?首先我们使用with语句用于打开文件.它不仅具有更多的pythonic和可读性,而且可以处理关闭,即使发生异常时也是如此.

接下来,我们创建一个DictReader从文件中读取行作为字典的行,自动使用第一行作为字段名称.然后我们让编写者回写我们的拆分文件,然后写入标题.使用DictReader是一个优先事项.它通常用于您经常访问数据的地方(当您不知道列的顺序时),但它使代码在这里可读性很好.但是,您可以使用标准csv.reader().

接下来,我们循环遍历文件中的行,检查年龄(我们将其转换为int,以便我们可以进行数值比较)以了解要写入的文件.该with声明为我们关闭了文件.

对于多个输入文件:

import csv

fieldnames = ["Name", "Date", "Age", "Sex", "Color"]
filenames = ["addressbook1.txt", "addressbook2.txt", ...]

with open("college_age.txt", "w") as college, open("adult_age.txt", "w") as adult:
   writer_college = csv.DictWriter(college, fieldnames, dialect="excel-tab")
   writer_adult = csv.DictWriter(adult, fieldnames, dialect="excel-tab")
   writer_college.writeheader()
   writer_adult.writeheader()
   for filename in filenames:
       with open(filename, "r") as input:
           reader = csv.DictReader(input, dialect="excel-tab")
           for row in reader:
               if int(row["Age"]) < 23:
                  writer_college.writerow(row)
               else:
                  writer_adult.writerow(row)
Run Code Online (Sandbox Code Playgroud)

我们只是添加一个循环来处理多个文件.请注意,我还添加了一个字段名称列表.在我刚刚使用文件中的字段和顺序之前,但由于我们有多个文件,我认为这样做更明智.另一种方法是使用第一个文件来获取字段名称.

  • @Brandon:猜测,换行是因为你在模式`w`打开文件.`csv`模块有一个怪癖,你需要在Windows上以`wb`模式打开文件.(如果他在Linux上,Lattyware可能没有这个问题.) (2认同)