Самый быстрый способ сделать преобразование типа данных с помощью csv.DictReader в Python

Я работаю с CSV-файлом в python, который будет иметь ~100 000 строк при использовании. Каждая строка имеет набор измерений (как строки) и одну метрику (float).

как csv.DictReader или CSV.reader возвращает значения только как string, в настоящее время я перебираю все строки и преобразую одно числовое значение в float.

for i in csvDict:
    i[col] = float(i[col])

есть ли лучший способ, который кто-нибудь может предложить сделать это? Я играл с различными комбинациями карт, izip, itertools и широко искали некоторые образцы более эффективного выполнения, но, к сожалению, не имели большого успеха.

в случае, если это помогает: Я делаю это на appengine. Я!--9-->верить то, что я делаю, может привести к тому, что я нажму эту ошибку: Превышен предел размера мягкого процесса с 267.789 MB после обслуживания всего 11 запросов - я получаю его только тогда, когда CSV довольно большой.

Edit: Моя Цель Я разбираю этот CSV, чтобы я мог использовать его как а источник данных для API визуализации Google. Окончательный набор данных будет загружен в Gviz DataTable для запроса. Тип должен быть указан при построении этой таблицы. Моя проблема также может быть решена, если кто-нибудь знает хороший конвертер gviz csv - >datatable в python!

Edit2: Мой Код

Я считаю, что моя проблема связана с тем, как я пытаюсь fixCsvTypes(). Кроме того, data_table в.LoadData () ожидает итерацию объект.

class GvizFromCsv(object):
  """Convert CSV to Gviz ready objects."""

  def __init__(self, csvFile, dateTimeFormat=None):
    self.fileObj = StringIO.StringIO(csvFile)
    self.csvDict = list(csv.DictReader(self.fileObj))
    self.dateTimeFormat = dateTimeFormat
    self.headers = {}
    self.ParseHeaders()
    self.fixCsvTypes()

  def IsNumber(self, st):
    try:
        float(st)
        return True
    except ValueError:
        return False

  def IsDate(self, st):
    try:
      datetime.datetime.strptime(st, self.dateTimeFormat)
    except ValueError:
      return False

  def ParseHeaders(self):
    """Attempts to figure out header types for gviz, based on first row"""
    for k, v in self.csvDict[0].items():
      if self.IsNumber(v):
        self.headers[k] = 'number'
      elif self.dateTimeFormat and self.IsDate(v):
        self.headers[k] = 'date'
      else:
        self.headers[k] = 'string'

  def fixCsvTypes(self):
    """Only fixes numbers."""
    update_to_numbers = []
    for k,v in self.headers.items():
      if v == 'number':
        update_to_numbers.append(k)
    for i in self.csvDict:
      for col in update_to_numbers:
        i[col] = float(i[col])

  def CreateDataTable(self):
    """creates a gviz data table"""
    data_table = gviz_api.DataTable(self.headers)
    data_table.LoadData(self.csvDict)
    return data_table

3 ответов


Я сначала использовал CSV-файл с регулярным выражением, но поскольку данные в файле очень строго расположены в каждой строке, мы можем просто использовать split () функции

import gviz_api

scheme = [('col1','string','SURNAME'),('col2','number','ONE'),('col3','number','TWO')]
data_table = gviz_api.DataTable(scheme)

#  --- lines in surnames.csv are : --- 
#  surname,percent,cumulative percent,rank\n
#  SMITH,1.006,1.006,1,\n
#  JOHNSON,0.810,1.816,2,\n
#  WILLIAMS,0.699,2.515,3,\n

with open('surnames.csv') as f:

    def transf(surname,x,y):
        return (surname,float(x),float(y))

    f.readline()
    # to skip the first line surname,percent,cumulative percent,rank\n

    data_table.LoadData( transf(*line.split(',')[0:3]) for line in f )
    # to populate the data table by iterating in the CSV file

или без функции, которая должна быть определена:

import gviz_api

scheme = [('col1','string','SURNAME'),('col2','number','ONE'),('col3','number','TWO')]
data_table = gviz_api.DataTable(scheme)

#  --- lines in surnames.csv are : --- 
#  surname,percent,cumulative percent,rank\n
#  SMITH,1.006,1.006,1,\n
#  JOHNSON,0.810,1.816,2,\n
#  WILLIAMS,0.699,2.515,3,\n

with open('surnames.csv') as f:

    f.readline()
    # to skip the first line surname,percent,cumulative percent,rank\n

    datdata_table.LoadData( [el if n==0 else float(el) for n,el in enumerate(line.split(',')[0:3])] for line in f )    
    # to populate the data table by iterating in the CSV file

в какой-то момент я считал, что должен заполнить таблицу данных одной строкой за раз, потому что я использовал регулярное выражение, и это необходимо для получения групп совпадений, прежде чем плавающие строки чисел. С split () все можно сделать в одной инструкции с LoadData ()

.

следовательно, ваш код может быть сокращен. Кстати, я не понимаю, почему он должен продолжать определять класс. Вместо этого функция кажется мне достаточной:

def GvizFromCsv(filename):
  """ creates a gviz data table from a CSV file """

  data_table = gviz_api.DataTable([('col1','string','SURNAME'),
                                   ('col2','number','ONE'    ),
                                   ('col3','number','TWO'    ) ])

  #  --- with such a table schema , lines in the file must be like that: ---  
  #  blah, number, number, ...anything else...\n 
  #  SMITH,1.006,1.006, ...anything else...\n 
  #  JOHNSON,0.810,1.816, ...anything else...\n 
  #  WILLIAMS,0.699,2.515, ...anything else...\n

  with open(filename) as f:
    data_table.LoadData( [el if n==0 else float(el) for n,el in enumerate(line.split(',')[0:3])]
                         for line in f )
  return data_table

.

Теперь вы должны проверить, можно ли вставить в этот код способ чтения данных CSV из другого API, чтобы сохранить принцип итерации для заполнения Таблицы данных.


во-первых, вы не нужно любое преобразование, если вам нужно только визуализируйте эти данные: gviz может обрабатывать JSON (текстовый, вы знаете) или CSV (у вас уже есть, не требуется разбор!). Вы можете поставить файл под вопрос на любом разумном веб-сервере и разрешить ему доступ с причудливыми запросами GET gviz, в основном игнорируя параметры.

но предположим, что вам нужна обработка. Похоже, вы не только читаете CSV-файл, но и пытаетесь храните его полностью в ОЗУ. Это может быть непрактично: вы нажмете RAM limit раньше и раньше, чем добавите больше обработки. Обрабатывайте данные по одной строке за раз (или разумное количество строк, Если вы применяете фильтры окон и т. д.) и помещайте обработанные строки в хранилище данных, а не в какой-либо список и т. д. Точно так же, при обслуживании данных через запрос GET, прочитайте / обработайте строку, напишите ее в ответ и не помещайте ее в какой-либо список или еще что-то.

Я не вижу проблем с техникой преобразования, пока вы используете i разумно позже в коде и не запомнить все iS, как вы идете.


есть две разные вещи: "источник данных"и" таблица данных".

"источник данных" - это имя форматированных данных, которые доставляются сервером Google Visualization API в качестве веб-службы визуализации:

This page describes how you can implement a data source to feed data
to visualizations built on the Google Visualization API. 

http://code.google.com/intl/fr/apis/visualization/documentation/dev/implementing_data_source.html 

название " источник данных "включает в себя понятие" проводной протокол":

In response [to a request], the data source returns properly formatted data 
that the visualization can use to render the graphic on the page. 
This request-response protocol is known as the Google Visualization API wire protocol,

http://code.google.com/intl/fr/apis/visualization/documentation/dev/implementing_data_source_overview.html

для реализации "источника данных" существует две возможности:

• Use one of the data source libraries listed in the Data Sources and Tools Gallery. 
All the data source libraries listed on that page implement the wire protocol.

• Write your own data source from scratch, 

http://code.google.com/intl/fr/apis/visualization/documentation/dev/implementing_data_source_overview.html

из следующего:

• ... Data Sources and Tools Gallery : (....) You therefore need write only the
code needed to make your data available to the library in the form of a data table. 

• Write your own data source from scratch, as described in the
Writing your own Data Source

Я понимаю, что с нуля нам нужно реализовать протокол wire + создание "таблицы данных", в то время как с библиотекой источников данных нам просто нужно создать"таблицу данных".


есть страницы по созданию " данных источник"

http://code.google.com/intl/fr/apis/visualization/documentation/dev/implementing_data_source_overview.html

http://code.google.com/intl/fr/apis/visualization/documentation/dev/gviz_api_lib.html

на мой взгляд, пример по адресу http://groups.google.com/group/google-visualization-api/browse_thread/thread/9d1d941e0f0b32ed речь идет о создании "источника данных" и ответа сделано там сомнительно. Но мне это не совсем ясно.


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

3.Prepare your data. You'll need to prepare the data to visualize; 
this means either specifying the data yourself in code, 
or querying a remote site for data.

http://code.google.com/intl/fr/apis/visualization/documentation/using_overview.html#keycomponents

A visualization stores the data that it visualizes as two-dimensional data table with 
rows and columns.
Cells are referenced by (row, column) where row is a zero-based row number, and column
is either a zero-based column index or a unique ID that you can specify. 

http://code.google.com/intl/fr/apis/visualization/documentation/using_overview.html#preparedata

таким образом, подготовка "таблицы данных" является ключевым моментом.

вот это:

There are two ways to create/populate your visualization's data table:

•Query a data provider. A data provider is another site that returns
a populated DataTable in response to a request from your code. 
Some data providers also accept SQL-like query strings to sort or 
filter the data. See Data Queries for more information and an example
of a query.

•Create and populate your own DataTable by hand. You can populate your
DataTable in code on your page. The simplest way to do this is to create
a DataTable object without any data and populate it by calling addRows()
on it. You can also pass a JavaScript literal representation of the data
table into the DataTable constructor, but this is more complex and is
covered on the reference page.

http://code.google.com/intl/fr/apis/visualization/documentation/using_overview.html#preparedata

дополнительная информация находится здесь:

2. Describe your table schema
The table schema is specified by the table_description parameter
passed into the constructor. You cannot change it later. 
The schema describes all the columns in the table: the data type of
each column, the ID, and an optional label.

Each column is described by a tuple: (ID [,data_type [,label [,custom_properties]]]). 



The table schema is a collection of column descriptor tuples. 
Every list member, dictionary key or dictionary value must be either 
another collection or a descriptor tuple. You can use any combination 
of dictionaries or lists, but every key, value, or member must
eventually evaluate to a descriptor tuple. Here are some examples.

•List of columns: [('a', 'number'), ('b', 'string')]
•Dictionary of lists: {('a', 'number'): [('b', 'number'), ('c', 'string')]}
•Dictionary of dictionaries: {('a', 'number'): {'b': 'number', 'c': 'string'}}
•And so on, with any level of nesting.


3. Populate your data
To add data to the table, build a structure of data elements in the
exact same structure as the table schema. So, for example, if your
schema is a list, the data must be a list: 

•schema: [("color", "string"), ("shape", "string")] 
•data: [["blue", "square"], ["red", "circle"]] 
If the schema is a dictionary, the data must be a dictionary:

•schema: {("rowname", "string"): [("color", "string"), ("shape", "string")] }
•data: {"row1": ["blue", "square"], "row2": ["red", "circle"]}

http://code.google.com/intl/fr/apis/visualization/documentation/dev/gviz_api_lib.html#populatedata

наконец, я бы сказал, что для вашей проблемы вам нужно определить "схему таблицы" и обработать ваш CSV-файл, чтобы получить a structure of data elements in the exact same structure as the table schema.

определение типа данных в столбце выполняется в определении" схема таблицы". Если заполнение "таблицы данных" должно быть сделано с данными, имеющих право тип (не строки, Я хочу сказать) Я помогу Вам написать код для извлечения данных из CSV, это просто делать.

На данный момент, я надеюсь, что все это правильно и поможет