Pandas чтение CSV с разделителем регулярных выражений - PullRequest
2 голосов
/ 10 апреля 2020

Я пытался прочитать пользовательский файл CSV, как это:

6 Rotterdam NLD Zuid-Holland 593321 
19 Zaanstad NLD Noord-Holland 135621 
214 Porto Alegre BRA Rio Grande do Sul 1314032 
397 Lauro de Freitas BRA Bahia 109236 
547 Dobric BGR Varna 100399 
552 Bujumbura BDI Bujumbura 300000 
554 Santiago de Chile CHL Santiago 4703954 
626 al-Minya EGY al-Minya 201360 
646 Santa Ana SLV Santa Ana 139389 
762 Bahir Dar ETH Amhara 96140 
123 Chicago 10000 
222 New York 200000  

Я попытался регулярное выражение в https://regex101.com/ Следующий код работает:

это работает

# https://regex101.com/
s = "6 Rotterdam NLD Zuid-Holland 593321 "
pat = r'(\d+)\s+([\D]+)\s(\d+)\s+'

m = re.match(pat,s)
m.groups() # ('6', 'Rotterdam NLD Zuid-Holland', '593321')

Я получил правильный ответ, но когда я применил код к pandas read_csv, он почему-то не сработал.

моя попытка

import numpy as np
import pandas as pd
from io import StringIO

s = """6 Rotterdam NLD Zuid-Holland 593321 
19 Zaanstad NLD Noord-Holland 135621 
214 Porto Alegre BRA Rio Grande do Sul 1314032 
397 Lauro de Freitas BRA Bahia 109236 
547 Dobric BGR Varna 100399 
552 Bujumbura BDI Bujumbura 300000 
554 Santiago de Chile CHL Santiago 4703954 
626 al-Minya EGY al-Minya 201360 
646 Santa Ana SLV Santa Ana 139389 
762 Bahir Dar ETH Amhara 96140 
123 Chicago 10000 
222 New York 200000  """;

sep = r'(\d+)\s+|([\D]+)\s+|(\d+)\s+'
df = pd.read_csv(StringIO(s), sep=sep,engine='python')
df

Я получаю много Нанс, как получить только 3 столбца?

Column names are: ID CITY POPULATION

аналогичные вопросы

Ответы [ 2 ]

2 голосов
/ 10 апреля 2020

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

Если может быть 1 , 2 или 3 цифры только в начале каждой строки, используйте

sep = r'(?:(?<=^\d)|(?<=^\d{2})|(?<=^\d{3}))\s+|\s+(?=\S+\s*$)'

См. Демонстрационный пример regex . Вы можете расширить его, добавив больше видов-слепков в первую группу без захвата.

Подробности

  • (?:(?<=^\d)|(?<=^\d{2})|(?<=^\d{3}))\s+ - 1+ пробелов (\s+) которым предшествует 1 ди git (\d) или 2 цифры (\d{2}) или 3 цифры (\d{3}) в начале строки (^)
  • | - или
  • \s+(?=\S+\s*$) - 1+ пробелов с 1+ непробельными символами и последующими 0+ пробелами до конца строки.
1 голос
/ 10 апреля 2020

Просто чтобы предоставить альтернативное решение без использования регулярных выражений:

Вы также можете выполнить синтаксический анализ текстового файла в обычном Python. В некоторых случаях это может быть легче поддерживать, чем довольно сложное регулярное выражение.

Для этого конкретного формата c мы знаем, что первое и последнее число в каждой строке имеют особое значение. Поэтому я бы использовал split и rsplit, чтобы выбрать их.

import pandas as pd
from io import StringIO

s = """6 Rotterdam NLD Zuid-Holland 593321 
19 Zaanstad NLD Noord-Holland 135621 
214 Porto Alegre BRA Rio Grande do Sul 1314032 
397 Lauro de Freitas BRA Bahia 109236 
547 Dobric BGR Varna 100399 
552 Bujumbura BDI Bujumbura 300000 
554 Santiago de Chile CHL Santiago 4703954 
626 al-Minya EGY al-Minya 201360 
646 Santa Ana SLV Santa Ana 139389 
762 Bahir Dar ETH Amhara 96140 
123 Chicago 10000 
222 New York 200000  """

data = []
for line in StringIO(s):
    line = line.strip()
    if not line:
        continue
    id_value, line = line.split(" ", 1)
    city, population = line.rsplit(" ", 1)

    data.append((id_value, city, population))

df = pd.DataFrame(data, columns=["id", "city", "population"])
df["id"] = pd.to_numeric(df["id"])
df["population"] = pd.to_numeric(df["population"])
print(df)

Я не делал никаких измерений скорости. Однако, в зависимости от размера файла, скорость может вообще не быть проблемой. Но даже если это так: я бы использовал этот сценарий для предварительной обработки данных сначала (и только один раз), чтобы иметь возможность использовать обычный старый pd.read_csv без дополнительных аргументов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...