Python在内存中分析表数据结构(dict, list, combo)



我试图模拟一些代码,我有SQL工作,但使用所有Python代替。这里有一些帮助CSV到Python字典与所有列名?

我现在可以读取我的压缩csv文件到字典只有一行,但最后一行。(如何获得行或整个数据文件的示例?)

我希望有一个内存驻留表,我可以像sql一样操作,当我完成例如清洁数据通过匹配坏数据到另一个表与坏数据和正确的条目。然后按类型、平均值、时间段等求和。总的数据文件大约有50万行。我不担心占用所有内存,但我希望尽我所能解决一般情况这样我就知道不用SQL

就能做什么了
import csv, sys, zipfile
sys.argv[0] = "/home/tom/Documents/REdata/AllListing1RES.zip"
zip_file    = zipfile.ZipFile(sys.argv[0])
items_file  = zip_file.open('AllListing1RES.txt', 'rU')
for row in csv.DictReader(items_file, dialect='excel', delimiter='t'):
    pass 
# Then is my result is
>>> for key in row:
print 'key=%s, value=%s' % (key, row[key])  
key=YEAR_BUILT_DESC, value=EXIST
key=SUBDIVISION, value=KNOLLWOOD
key=DOM, value=2
key=STREET_NAME, value=ORLEANS RD
key=BEDROOMS, value=3
key=SOLD_PRICE, value=
key=PROP_TYPE, value=SFR
key=BATHS_FULL, value=2
key=PENDING_DATE, value=
key=STREET_NUM, value=3828
key=SOLD_DATE, value=
key=LIST_PRICE, value=324900
key=AREA, value=200
key=STATUS_DATE, value=3/3/2011 11:54:56 PM
key=STATUS, value=A
key=BATHS_HALF, value=0
key=YEAR_BUILT, value=1968
key=ZIP, value=35243
key=COUNTY, value=JEFF
key=MLS_ACCT, value=492859
key=CITY, value=MOUNTAIN BROOK
key=OWNER_NAME, value=SPARKS
key=LIST_DATE, value=3/3/2011
key=DATE_MODIFIED, value=3/4/2011 12:04:11 AM 
key=PARCEL_ID, value=28-15-3-009-001.0000
key=ACREAGE, value=0
key=WITHDRAWN_DATE, value=
>>>

我想我找错人了…一是我的数据文件大约有50万行,但只有一行。二是字典似乎不是正确的结构,因为我不认为我可以加载所有50万行,并对它们进行各种操作。比如…按小组和日期求和…此外,似乎重复的键可能会导致问题,如非唯一的描述符,如县和细分。

我也不知道如何在加载所有(我也没有得到…)之前将行的特定小子集读入内存(如10或100进行测试)。我已经阅读了Python文档和几本参考书,但它仍然没有点击…

似乎我能找到的大多数答案都建议使用各种SQL解决方案来解决这类问题,但我渴望学习使用Python实现类似结果的基础知识。在某些情况下,我认为这将更容易、更快,并扩展我的工具集。但是我很难找到相关的例子。

有一个答案暗示了我的意思:

一旦读取正确完成,DictReader应该可以将行作为字典(一种典型的面向行的结构)来获取。奇怪的是,这通常不是处理像你这样的查询的有效方式;只有列列表使搜索更容易。面向行意味着您必须为每一行重新做一些查找工作。像日期匹配这样的事情需要的数据肯定不在CSV中,比如日期是如何表示的,哪些列是日期。

获取面向列的数据结构的示例(但是,涉及加载整个文件):

import csv
allrows=list(csv.reader(open('test.csv')))
# Extract the first row as keys for a columns dictionary
columns=dict([(x[0],x[1:]) for x in zip(*allrows)])
The intermediate steps of going to list and storing in a variable aren't necessary. 
The key is using zip (or its cousin itertools.izip) to transpose the table.
Then extracting column two from all rows with a certain criterion in column one:
matchingrows=[rownum for (rownum,value) in enumerate(columns['one']) if value>2]
print map(columns['two'].__getitem__, matchingrows)
When you do know the type of a column, it may make sense to parse it, using appropriate 
functions like datetime.datetime.strptime.

via Yann游标

对于这个一般性的话题,肯定有一些好的参考资料吧?

您一次只能从csv阅读器中读取一行,但是您可以很容易地将它们全部存储在内存中:

rows = []
for row in csv.DictReader(items_file, dialect='excel', delimiter='t'):
    rows.append(row)
# rows[0]
{'keyA': 13, 'keyB': 'dataB' ... }
# rows[1]
{'keyA': 5, 'keyB': 'dataB' ... }

然后,进行聚合和计算:

sum(row['keyA'] for row in rows)

您可能希望在数据进入rows之前对其进行转换,或者使用更友好的数据结构。每次计算迭代超过500,000行可能会变得非常低效。

正如一位评论者所提到的,使用内存数据库可能对您非常有益。另一个问题是如何将CSV数据传输到sqlite数据库。

import csv
import sqlite3
conn = sqlite3.connect(":memory:")
c = conn.cursor()
c.execute("create table t (col1 text, col2 float);")
# csv.DictReader uses the first line in the file as column headings by default
dr = csv.DictReader(open('data.csv', delimiter=','))
to_db = [(i['col1'], i['col2']) for i in dr]
c.executemany("insert into t (col1, col2) values (?, ?);", to_db)

你说""我现在可以读取我的压缩csv文件到字典只有一行,但最后一行。(我如何获得一行的样本或整个数据文件?)"

你的代码是这样做的:

for row in csv.DictReader(items_file, dialect='excel', delimiter='t'):
    pass

我无法想象你为什么写这个,但效果是一行一行地读取整个输入文件,忽略每一行 (pass意味着"什么都不做")。最终的结果是,row指的是最后一行(当然,除非文件是空的)。

要"获取"整个文件,将pass更改为do_something_useful_with(row)

如果您想将整个文件读入内存,只需这样做:

rows = list(csv.DictReader(.....))

获取一个样本,例如每N行(N> 0),从第M行开始(0 <= M <N),执行如下操作:>

for row_index, row in enumerate(csv.DictReader(.....)):
    if row_index % N != M: continue
    do_something_useful_with(row)

顺便说一下,你不需要dialect='excel';

Numpy(数值python)是操作、比较等数组的最佳工具,你的表基本上是一个2d数组。

最新更新