我正在尝试获取事务数据列表并将其总和为2d numpy数组。我的数据如下所示:
person, product, date, val
A, x, 1/1/2013, 10
A, x, 1/10/2013, 10
B, x, 1/2/2013, 20
B, y, 1/4/2013, 15
A, y, 1/8/2013, 20
C, z, 2/12/2013, 40
我需要将输出变为二维数组,每个人作为一行,产品作为列。日期将被删除,值将相加。
输出将如下所示:
[[20, 20, 0],[20, 15, 0],[0, 0, 40]]
这就是我的功能,但它真的很慢(我有110,000,000条记录):
import numpy as np
from collections import defaultdict
from sklearn.feature_extraction import DictVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
import pandas as pd
from scipy import sparse
import os
import assoc
#read in data to a dict object - sums scripts by tuple (doc, drug)
dictObj = {}
rawData = 'subset.txt'
with open(rawData) as infile:
for line in infile:
parts = line.split(',')
key = (parts[0],parts[1])
val = float(parts[3])
if key in dictObj:
dictObj[key] += val
else:
dictObj[key] = val
infile.close()
print "stage 1 done"
#get the number of doctors and the number of drugs
keys = dictObj.keys()
docs = list(set([x[0] for x in keys]))
drugs = sorted(list(set([x[1] for x in keys])))
#read through the dict and build out a 2d numpy array
docC = 0
mat = np.empty([len(docs),len(drugs)])
for doc in docs:
drugC = 0
for drug in drugs:
key = (doc,drug)
if key in dictObj:
mat[(docC,drugC)] = dictObj[(key)]
else:
mat[(docC,drugC)] = 0
drugC += 1
docC+=1
我之前发布了一个类似的帖子(这里是Transformation of transactions to numpy array),每个人都回答说Pandas是要走的路,但我不能为我的生活让Pandas输出成正确的格式。我不能将Pandas dataFrame传递给我的kmeans或apriori算法,无论我如何安排dataFrame,df.values都会让我进入multiIndex系列(简化为1长数组!)。任何指针都将非常感谢!
答案 0 :(得分:4)
我可能会做类似
的事情>>> df = pd.read_csv("trans.csv", skipinitialspace=True)
>>> w = df.groupby(["person", "product"])["val"].sum().reset_index()
>>> w
person product val
0 A x 20
1 A y 20
2 B x 20
3 B y 15
4 C z 40
>>> w.pivot("person", "product").fillna(0)
val
product x y z
person
A 20 20 0
B 20 15 0
C 0 0 40
>>> w.pivot("person", "product").fillna(0).values
array([[ 20., 20., 0.],
[ 20., 15., 0.],
[ 0., 0., 40.]])
哪个IIUC是您所追求的二维阵列。请注意,您不必一次将整个文件读入内存,您可以使用chunksize
参数(请参阅the docs here)并逐个累积您的表格。
答案 1 :(得分:1)
recfromcsv
(或recfromtxt)会将您的数据加载到记录数组中
data=np.recfromcsv('stack20179393.txt')
rec.array([('A', ' x', ' 1/1/2013', 10), ('A', ' x', ' 1/10/2013', 10),
('B', ' x', ' 1/2/2013', 20), ('B', ' y', ' 1/4/2013', 15),
('A', ' y', ' 1/8/2013', 20), ('C', ' z', ' 2/12/2013', 40)],
dtype=[('person', 'S1'), ('product', 'S2'), ('date', 'S10'), ('val', '<i4')])
data.person
# chararray((['A', 'A', 'B', 'B', 'A', 'C'], dtype='|S1')
data.val
# array([10, 10, 20, 15, 20, 40])
由于person
可以按任何顺序出现,并且频率不同(3A,2B,1C),因此您无法轻易将其转换为2D数组。因此,您可能仍需要遍历记录,在字典中收集值 - 我建议使用collections.defaultdict
。 itertools.groupby
也是将值集合到一起的便捷工具。但是,它需要对记录进行排序。
使用defaultdict
from collections import defaultdict
dd = defaultdict(list)
for row in data:
dd[row[0]].append(row[-1])
print dd
# defaultdict(<type 'list'>, {'A': [10, 10, 20], 'C': [40], 'B': [20, 15]})
d = {}
for k,v in dd.items(): d[k] = sum(v)
print d
# {'A': 40, 'B': 35, 'C': 40}
或
dd = defaultdict(float)
for row in data:
dd[row[0]].append(row[-1])
print dd
defaultdict(<type 'float'>, {'A': 40.0, 'C': 40.0, 'B': 35.0})
稀疏方法利用csr_matrix
对重复索引求和的方式
from scipy import sparse
row=np.array([ord(a) for a in data.person])-65
col=np.zeros(row.shape)
sparse.csr_matrix((data.val,(row,col))).T.A
# array([[40, 35, 40]])
答案 2 :(得分:0)
根据问题的结束,您似乎只需要将pandas DataFrame
添加到numpy array
。这是你如何做到的:
#df is your DataFrame
data = np.asarray(df)
所以现在你应该没有使用熊猫的问题!
答案 3 :(得分:0)
查看您的代码和数据大小,我认为这将是非常缓慢的110,000,000条记录,可能包括字符串,(医生),长字符串,(药物),日期(丢弃)和值这是一个浮点值。让我们说20个医生的角色,(可能还不够),30个用于药物,(可能还不够),4个字节的价值是5.5 Gi之前的任何开销,然后你将它复制到一个二维矩阵。
除非您在大型机或群集上运行,否则我强烈建议重组为在您阅读时加总或将第1阶段读入数据库。
如果Pandas不适合您,您还可以查看使用pytables的可能性。