我有一个标签分隔文件,其中包含 10亿行(想象200列,而不是3列):
abc -0.123 0.6524 0.325
foo -0.9808 0.874 -0.2341
bar 0.23123 -0.123124 -0.1232
我想创建一个字典,其中第一列中的字符串是键,其余是值。我一直在这样做,但计算成本很高:
import io
dictionary = {}
with io.open('bigfile', 'r') as fin:
for line in fin:
kv = line.strip().split()
k, v = kv[0], kv[1:]
dictionary[k] = list(map(float, v))
我怎样才能获得所需的字典?实际上,numpy数组比值的浮点数列表更合适。
答案 0 :(得分:4)
你可以使用pandas加载df,然后根据需要构建一个新的df,然后调用to_dict
:
In [99]:
t="""abc -0.123 0.6524 0.325
foo -0.9808 0.874 -0.2341
bar 0.23123 -0.123124 -0.1232"""
df = pd.read_csv(io.StringIO(t), sep='\s+', header=None)
df = pd.DataFrame(columns = df[0], data = df.ix[:,1:].values)
df.to_dict()
Out[99]:
{'abc': {0: -0.12300000000000001,
1: -0.98080000000000001,
2: 0.23123000000000002},
'bar': {0: 0.32500000000000001, 1: -0.2341, 2: -0.1232},
'foo': {0: 0.65239999999999998, 1: 0.87400000000000011, 2: -0.123124}}
修改强>
一种更动态的方法,可以减少构建临时df的需要:
In [121]:
t="""abc -0.123 0.6524 0.325
foo -0.9808 0.874 -0.2341
bar 0.23123 -0.123124 -0.1232"""
# determine the number of cols, we'll use this in usecols
col_len = pd.read_csv(io.StringIO(t), sep='\s+', nrows=1).shape[1]
col_len
# read the first col we'll use this in names
cols = pd.read_csv(io.StringIO(t), sep='\s+', usecols=[0], header=None)[0].values
# now read and construct the df using the determined usecols and names from above
df = pd.read_csv(io.StringIO(t), sep='\s+', header=None, usecols = list(range(1, col_len)), names = cols)
df.to_dict()
Out[121]:
{'abc': {0: -0.12300000000000001,
1: -0.98080000000000001,
2: 0.23123000000000002},
'bar': {0: 0.32500000000000001, 1: -0.2341, 2: -0.1232},
'foo': {0: 0.65239999999999998, 1: 0.87400000000000011, 2: -0.123124}}
进一步更新
实际上你不需要第一次读取,列长度可以隐含地通过第一列中的列数得出:
In [128]:
t="""abc -0.123 0.6524 0.325
foo -0.9808 0.874 -0.2341
bar 0.23123 -0.123124 -0.1232"""
cols = pd.read_csv(io.StringIO(t), sep='\s+', usecols=[0], header=None)[0].values
df = pd.read_csv(io.StringIO(t), sep='\s+', header=None, usecols = list(range(1, len(cols)+1)), names = cols)
df.to_dict()
Out[128]:
{'abc': {0: -0.12300000000000001,
1: -0.98080000000000001,
2: 0.23123000000000002},
'bar': {0: 0.32500000000000001, 1: -0.2341, 2: -0.1232},
'foo': {0: 0.65239999999999998, 1: 0.87400000000000011, 2: -0.123124}}
答案 1 :(得分:3)
如果指定列数,则可以使用numpy.genfromtxt()
函数:
import numpy as np
a = np.genfromtxt('bigfile.csv',dtype=str,usecols=(0))
b = np.genfromtxt('bigfile.csv',dtype=float,delimiter='\t',usecols=range(1,4))
#^enter # of cols here
d = dict(zip(a,b.tolist())) #if you want a numpy array, just remove .tolist()
print d
<强>输出:强>
{'abc': [-0.123, 0.6524, 0.325], 'bar': [0.23123, -0.123124, -0.1232], 'foo': [-0.9808, 0.874, -0.2341]}
注意:要以编程方式查找您可以执行的cols
的数量:
with open('bigfile.csv', 'r') as f:
num_cols = len(f.readline().split())
然后使用num_cols
作为usecols
参数。
答案 2 :(得分:2)
您可以使用csv
模块来读取文件,以便分割线然后使用np.array
将浮点值转换为numpy数组对象:
import csv
import numpy as np
dictionary = {}
with open('bigfile.csv', 'rb') as csvfile:
spamreader = csv.reader(csvfile, delimiter='\t',)
for row in spamreader:
k, v = row[0], row[1:] #in python3 do k,*v = row
dictionary[k] = np.array(map(float, v))
答案 3 :(得分:0)
使用Pandas
的一种方法。假设你做df = pd.read_csv(file)
而df
就像
In [220]: df
Out[220]:
k a1 a2 a3
0 abc -0.12300 0.652400 0.3250
1 foo -0.98080 0.874000 -0.2341
2 bar 0.23123 -0.123124 -0.1232
我添加了虚拟列名称,您可以灵活地在读取csv文件时更改它
然后你可以做到以下几点。
In [221]: df.set_index('k').T.to_dict('list')
Out[221]:
{'abc': [-0.12300000000000001, 0.65239999999999998, 0.32500000000000001],
'bar': [0.23123000000000002, -0.123124, -0.1232],
'foo': [-0.98080000000000001, 0.87400000000000011, -0.2341]}
答案 4 :(得分:0)
对不起,这不是一个真正的答案,但对评论来说太长了。
你说你有10亿行,有200列浮点数。它意味着
的最小记忆10 9 * 200 * 8 = 1.6 10 12 bytes
它提供超过1.5 G不计算字典的开销。
当然,您可以尝试使用numpy
数组而不是浮点数列表,但每个数组都很小(200个元素),因此我非常怀疑增益是否很重要。
恕我直言,对于这么多数据,你不应该考虑加载阶段而不管你如何处理数据,如果你真的需要一个包含10个记录的200个浮点值的字典,你当前实现是正确的,因为是一个numpy数组。
如果您可以将所有数据放在一个numpy数组中,并且确实将numpy用于处理部分,那么您可以获得进一步处理的重要收益,但不知道更多它只是推测。