Манипулирование TSV файлом

У меня есть.tv файл текстовых данных, связанных здесь: данные мировых банков

Мне нужно прочитать данные в структуре данных (любая структура данных), сохранить только строки с датой "7/1/2000" или 7/1/2010 "и сохранить только 7 из 19 оригинальных столбцов. но я думал, что это будет довольно простая задача. У меня есть код, который является неполным:

import math
import csv
import re


fhand=open("world_bank_indicators.txt", "rU")
reader=csv.reader(fhand, dialect="excel", delimiter="\t",skipinitialspace=True)

data=dict()
mylist=list()

#doesn't print headers, however
for row in reader:
 if row[1]=="7/1/2000" or row[1]=="7/1/2010":
 print row[0], row[1], row[9], row[4], row[6], row[5], row[19]

UPDATE, версия с помощью dictreader:

import math
import csv
import re

fhand=open("world_bank_indicators.txt", "rU")
reader=csv.reader(fhand, dialect="excel", delimiter="\t", lineterminator="\n")

reader=csv.DictReader(fhand, delimiter="\t")
myset=set()
mydict=dict()
mylist=list()

for row in reader:
 mydict["Date"]=row["Date"]

print mydict

однако, похоже, это только запись одной записи {date: 7/1/2010} в мой dict

поэтому, мои очевидные проблемы:

1) это печатает строки и столбцы данных, которые я хочу, однако они не печатают заголовки каждого столбца 2) очевидно, что ничто не было добавлено ни в какую структуру данных, чтобы я мог выполнять любые вычисления с данными

что (мучительно очевидно, я уверен), что я здесь пропал? Как я могу выполнить эти две простые задачи?

1 ответ

Во-первых, чтобы напечатать заголовки, все, что вам нужно сделать, это распечатать столбцы первой строки, так же, как и для всех 7/1/2000 строк 7/1/2000. Например:

headers = next(reader)
print row[0], row[1], row[9], row[4], row[6], row[5], row[19]

for row in reader:
 if row[1]=="7/1/2000" or row[1]=="7/1/2010":
 print row[0], row[1], row[9], row[4], row[6], row[5], row[19]

Однако это не означает создание TSV; вы просто разделяете столбцы на одно пространство. Плюс, конечно, вы просто print их в stdout, не записывая их в файл. Самое простое решение - использовать csv.writer же, как вы использовали csv.reader:

writer=csv.writer(outfile, dialect="excel", delimiter="\t",skipinitialspace=True)
# …
writer.writerow(row[0], row[1], row[9], row[4], row[6], row[5], row[19])

Чтобы сделать это немного чище и не повторяйте этот список столбцов дважды, вы можете использовать operator.itemgetter, например:

columns = 0, 1, 9, 4, 6, 5, 19
getter = operator.itemgetter(*columns)
# ...
writer.writerow(getter(row))

Если вы хотите сохранить значения, а не записывать их, просто передайте их методу append объекта list, а writerow метод csv.writer объекта csv.writer. (Вероятно, вы также хотите сохранить headers.)

headers = getter(next(reader))

data = []
for row in reader:
 if row[1]=="7/1/2000" or row[1]=="7/1/2010":
 data.append(getter(row))

Вы можете сделать это более кратким с пониманием:

data = [getter(row) for row in reader if row[1]=="7/1/2000" or row[1]=="7/1/2010"]

Если вы хотите использовать DictReader, вы больше не получите столбцы по индексу, вы получите их по имени. Кроме того, DictReader автоматически потребляет строку заголовка, чтобы определить эти имена. Здесь упрощенный пример. Представьте, что это были ваши данные:

name,email,rank
Joe,[removed_email],7
Jim,[removed_email],12
Jen,[removed_email],2

И позвольте сказать, что мы просто хотели, чтобы электронная почта людей в первой десятке. Итак, вот она с reader:

reader = csv.reader(f)
headers = next(reader)
data = [row[1] for row in reader if int(row[2]) < 10]

И вот он с DictReader:

reader = csv.DictReader(f)
data = [row['email'] for row in reader if int(row['rank']) < 10]

Это может быть не столь кратким, но, вероятно, более читаемым.

licensed under cc by-sa 3.0 with attribution.