Python: дополнительная запятая в столбце csv.Dictreader - PullRequest
1 голос
/ 14 марта 2019

У меня есть эта функция чтения, где он читает файл CSV, используя csv.DictReader. Файл.csv разделен запятыми и полностью читается. Тем не менее, эта часть моего файла имеет столбец, который содержит несколько запятых. У меня вопрос, как я могу убедиться, что запятая считается частью столбца? Я не могу изменить свой CSV-файл, чтобы соответствовать критериям.

Текстовый файл :

ID,Name,University,Street,ZipCode,Country
12,Jon Snow,U of Winterfell,Winterfell #45,60434,Westeros
13,Steve Rogers,NYU,108, Chelsea St.,23333,United States
20,Peter Parker,Yale,34, Tribeca,32444,United States
34,Tyrion Lannister,U of Casterly Rock,Kings Landing #89, 43543,Westeros

Требуемый вывод:

{'ID': '12', 'Name': 'Jon Snow', 'University': 'U of Winterfell', 'Street': 'Winterfell #45', 'ZipCode': '60434', 'Country': 'Westeros'}
{'ID': '13', 'Name': 'Steve Rogers', 'University': 'NYU', 'Street': '108, Chelsea St.', 'ZipCode': '23333', 'Country': 'United States'}
{'ID': '20', 'Name': 'Peter Parker', 'University': 'Yale', 'Street': '34, Tribeca', 'ZipCode': '32444', 'Country': 'United States'}
{'ID': '34', 'Name': 'Tyrion Lannister', 'University': 'U of Casterly Rock', 'Street': 'Kings Landing #89', 'ZipCode': '43543', 'Country': 'Westeros'}

Как вы можете сказать, "Улица" имеет как минимум две запятые из-за чисел:

13, Стив Роджерс, NYU, 108, Chelsea St. , 23333, Соединенные Штаты

20, Питер Паркер, Йель, 34, Трибека , 32444, Соединенные Штаты

Примечание: Большинство читаемых столбцов разделяется на str, str НО под столбцом 'Street', за ним следует str, str (после запятой есть дополнительный пробел). Я надеюсь это имеет смысл.

В опциях, которые я пытался найти, используется re.split, но я не знаю, как реализовать это в моем файле для чтения. Я думал re.split(r'(?!\s),(?!\s)',x[:-1])? Как я могу убедиться, что формат из моего файла будет считаться частью любого столбца? Я не могу использовать панд.

Мой текущий вывод выглядит следующим образом:

{'ID': '12', 'Name': 'Jon Snow', 'University': 'U of Winterfell', 'Street': 'Winterfell #45', 'ZipCode': '60434', 'Country': 'Westeros'}
{'ID': '13', 'Name': 'Steve Rogers', 'University': 'NYU', 'Street': '108', 'ZipCode': 'Chelsea St.', 'Country': '23333', None: ['United States']}
{'ID': '20', 'Name': 'Peter Parker', 'University': 'Yale', 'Street': '34', 'ZipCode': 'Tribeca', 'Country': '32444', None: ['United States']}
{'ID': '34', 'Name': 'Tyrion Lannister', 'University': 'U of Casterly Rock', 'Street': 'Kings Landing #89', 'ZipCode': '43543', 'Country': 'Westeros'}

Это моя функция чтения:

import csv

list = []
with open('file.csv', mode='r') as csv_file:
  csv_reader = csv.DictReader(csv_file, delimiter=",", skipinitialspace=True)

  for col in csv_reader:
    list.append(dict(col))
    print(dict(col))

Ответы [ 2 ]

1 голос
/ 14 марта 2019

Нельзя использовать csv, если файл недопустим в формате CSV.

Вам необходимо вызывать re.split() по обычным строкам, а не по словарям.

list = []
with open('file.csv', mode='r') as csv_file:
    keys = csv_file.readline().strip().split(',') # Read header line
    for line in csv_file:
        line = line.strip()
        row = re.split(r'(?!\s),(?!\s)',line)
        list.append(dict(zip(keys, row)))
0 голосов
/ 14 марта 2019

Фактическим решением проблемы является изменение скрипта, который генерирует CSV-файл.

Если у вас есть возможность изменить этот вывод, вы можете сделать 2 вещи

  • Используйте разделитель, отличный от запятой, такой как | символ или ;, независимо от того, что, по вашему мнению, в строке не существует.
  • Или заключите все столбцы в ", чтобы их можно было разделить на ,, которые являются фактическими разделителями.

Если у вас нет возможности изменить вывод.

И если вы уверены, что несколько запятых есть только в столбце улицы; тогда вы должны использовать csv.reader вместо DictReader, чтобы вы могли получить столбцы по индексам, в которых вы уже уверены. например, row[0] будет ID row[1] будет Name, а row[-1] будет Country row[-2] будет ZipCode, поэтому row[2:-2] даст вам то, что вам нужно, я думаю. Индексы можно расположить, но идея ясна.

Надеюсь, это поможет.


Edit:

import csv

list = []
with open('file.csv', mode='r') as csv_file:
  csv_reader = csv.reader(csv_file, delimiter=",", skipinitialspace=True)
  # pass the header row
  next(csv_reader)
  for row in csv_reader:
  list.append({"ID": row[0],
               "Name": row[1],
               "University": row[2],
               "Street": ' '.join(row[3:-2]),
               "Zipcode": row[-2],
               "Country": row[-1]})
print(list)

- Вот вывод (с pprint)

[{'Country': 'Westeros',
'ID': '12',
'Name': 'Jon Snow',
'Street': 'Winterfell #45',
'University': 'U of Winterfell',
'Zipcode': '60434'},
{'Country': 'United States',
'ID': '13',
'Name': 'Steve Rogers',
'Street': '108 Chelsea St.',
'University': 'NYU',
'Zipcode': '23333'},
 {'Country': 'United States',
'ID': '20',
'Name': 'Peter Parker',
'Street': '34 Tribeca',
'University': 'Yale',
'Zipcode': '32444'},
 {'Country': 'Westeros',
'ID': '34',
'Name': 'Tyrion Lannister',
'Street': 'Kings Landing #89',
'University': 'U of Casterly Rock',
'Zipcode': '43543'}]

- второе редактирование отредактировал указатель на улице. С уважением.

...