Метод угадывания типа данных, представленных в настоящее время в виде строк - PullRequest
2 голосов
/ 23 июня 2010

В настоящее время я анализирую таблицы CSV, и мне нужно обнаружить «типы данных» столбцов.Я не знаю точный формат значений.Очевидно, что все, что выводит анализатор CSV, является строкой.В настоящее время меня интересуют следующие типы данных:

  1. целое число
  2. с плавающей запятой
  3. дата
  4. логическое значение
  5. строка

В настоящее время я думаю о том, чтобы протестировать выборку строк (может быть, несколько сотен?), Чтобы определить типы данных, представленных в сопоставлении с образцом.

Меня особенно беспокоит тип данных date - это модуль python для анализа общих идиом даты (очевидно, я не смогу обнаружить их все) ?

А как насчет целых чисел и чисел?

Ответы [ 5 ]

3 голосов
/ 23 июня 2010

ast.literal_eval() могут получить легкие.

3 голосов
/ 23 июня 2010

Dateutil приходит на ум при разборе дат.

Для целых чисел и чисел с плавающей точкой вы всегда можете попробовать приведение в секции try / кроме

>>> f = "2.5"
>>> i = "9"
>>> ci = int(i)
>>> ci
9
>>> cf = float(f)
>>> cf
2.5
>>> g = "dsa"
>>> cg = float(g)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid literal for float(): dsa
>>> try:
...   cg = float(g)
... except:
...   print "g is not a float"
...
g is not a float
>>>
2 голосов
/ 25 октября 2014

Возможно, вас заинтересует эта библиотека Python, которая выполняет именно такие предположения типов как для общих данных Python, так и для файлов CSV и XLS:

Он легко масштабируется до очень больших файлов, потоковой передачи данных из Интернета и т. Д.

Существует также еще более простая библиотека-оболочка, включающая командную строкуинструмент с именем преобразователи данных: http://okfnlabs.org/dataconverters/ (и онлайн-сервис: https://github.com/okfn/dataproxy!)

Основной алгоритм, который делает угадывание типа здесь: https://github.com/okfn/messytables/blob/7e4f12abef257a4d70a8020e0d024df6fbb02976/messytables/types.py#L164

2 голосов
/ 23 июня 2010

В настоящее время меня интересуют типы данных ...

Они не существуют в файле CSV.Данные только строки.Только.Ничего больше.

проверить образец строк

Ничего не говорит вам, кроме того, что вы видели в образце.Следующая строка после вашей выборки может быть строкой, которая выглядит совершенно иначе, чем строки выборки.

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

Если столбец 1 должен быть датой, вам придется посмотреть на строку и определить формат.Это может быть что угодно.Число, типичная григорианская дата в американском или европейском формате (нет способа узнать, является ли 1/1/10 американским или европейским).

try:
    x= datetime.datetime.strptime( row[0], some format )
except ValueError:
    # column is not valid.

Если столбец 2 должен быть плавающим, выможет только это сделать.

try:
    y= float( row[1] )
except ValueError:
    # column is not valid.

Если столбец 3 должен быть целым числом, вы можете сделать это только.

try:
    z= int( row[2] )
except ValueError:
    # column is not valid.

Нет способа "обнаружить", если CSVимеет строки с плавающей запятой, за исключением выполнения float в каждой строке.Если строка не удалась, кто-то неправильно подготовил файл.

Поскольку вам нужно выполнить преобразование, чтобы увидеть, возможно ли преобразование, вы можете просто обработать строку.Это проще и дает вам результаты за один проход.

Не тратьте время на анализ данных.Спросите людей, которые его создали, что там должно быть 1030 *.

1 голос
/ 28 января 2019

Мы протестировали ast.literal_eval(), но спасение от ошибки происходит довольно медленно, если вы хотите преобразовать данные, которые вы получаете как string, я думаю, что регулярное выражение будет быстрее.работал очень хорошо для нас.

import datetime
import re

"""
Helper function to detect the appropriate type for a given string.
"""
def guess_type(s):
    if re.match("\A[0-9]+\.[0-9]+\Z", s):
        return float
    elif re.match("\A[0-9]+\Z", s):
        return int
    # 2019-01-01 or 01/01/2019 or 01/01/19
    elif re.match("\A[0-9]{4}-[0-9]{2}-[0-9]{2}\Z", s) or \
         re.match("\A[0-9]{2}/[0-9]{2}/([0-9]{2}|[0-9]{4})\Z", s): 
        return datetime.date
    elif re.match("\A(true|false)\Z", s):
        return bool
    else:
        return str

Тесты:

assert guess_type("this is a string") == str
assert guess_type("0.1") == float
assert guess_type("true") == bool
assert guess_type("1") == int
assert guess_type("2019-01-01") == datetime.date
assert guess_type("01/01/2019") == datetime.date
assert guess_type("01/01/19") == datetime.date
...