【发布时间】:2011-02-02 09:31:28
【问题描述】:
我的问题不是关于特定的代码 sn-p 而是更笼统的,所以请多多包涵:
我应该如何组织我正在分析的数据,我应该使用哪些工具来管理它?
我正在使用 python 和 numpy 来分析数据。因为python文档表明字典在python中是非常优化的,而且由于数据本身非常结构化,所以我将它存储在一个深度嵌套的字典中。
这里是字典的骨架:层次结构中的位置定义了元素的性质,每个新行定义了前级中一个键的内容:
[AS091209M02] [AS091209M01] [AS090901M06] ...
[100113] [100211] [100128] [100121]
[R16] [R17] [R03] [R15] [R05] [R04] [R07] ...
[1263399103] ...
[ImageSize] [FilePath] [Trials] [Depth] [Frames] [Responses] ...
[N01] [N04] ...
[Sequential] [Randomized]
[Ch1] [Ch2]
编辑:为了更好地解释我的数据集:
[individual] ex: [AS091209M02]
[imaging session (date string)] ex: [100113]
[Region imaged] ex: [R16]
[timestamp of file] ex [1263399103]
[properties of file] ex: [Responses]
[regions of interest in image ] ex [N01]
[format of data] ex [Sequential]
[channel of acquisition: this key indexes an array of values] ex [Ch1]
我执行的操作类型是例如计算数组的属性(列在 Ch1、Ch2 下),拾取数组以创建新集合,例如分析来自给定区域 16 (R16) 的 N01 的响应个人在不同时间点等。
这种结构对我来说效果很好,而且速度非常快,正如我所承诺的那样。我可以很快分析完整的数据集(而且字典太小,无法填满我电脑的内存:半个演出)。
我的问题来自于我需要对字典的操作进行编程的繁琐方式。我经常有这样一段代码:
for mk in dic.keys():
for rgk in dic[mk].keys():
for nk in dic[mk][rgk].keys():
for ik in dic[mk][rgk][nk].keys():
for ek in dic[mk][rgk][nk][ik].keys():
#do something
它丑陋、笨重、不可重复使用且易碎(需要为字典的任何变体重新编码)。
我尝试使用递归函数,但除了最简单的应用程序之外,我还遇到了一些非常讨厌的错误和奇怪的行为,这导致了大量的时间浪费(我没有设法在 ipython 中使用 pdb 进行调试,这无济于事当我处理深度嵌套的递归函数时)。最后,我经常使用的唯一递归函数如下:
def dicExplorer(dic, depth = -1, stp = 0):
'''prints the hierarchy of a dictionary.
if depth not specified, will explore all the dictionary
'''
if depth - stp == 0: return
try : list_keys = dic.keys()
except AttributeError: return
stp += 1
for key in list_keys:
else: print '+%s> [\'%s\']' %(stp * '---', key)
dicExplorer(dic[key], depth, stp)
我知道我做错了,因为我的代码很长、简单且不可重用。我需要使用更好的技术来灵活地操作字典,或者将数据放入某种数据库格式(sqlite?)。我的问题是,由于我在编程方面(非常)自学,我缺乏实践经验和背景知识来欣赏可用的选项。我已经准备好学习新工具(SQL、面向对象的编程),不惜一切代价来完成工作,但我不愿意将我的时间和精力投入到对我的需求来说是死胡同的事情上。
那么对于解决这个问题,以及能够以更简洁、灵活和可重用的方式编写我的工具,您有什么建议?
附录:除了对数据字典的特定子字典进行操作之外,以下是我为数据集 dic 或其子字典实现的一些操作示例:
实际上我有一些运行良好的递归函数:
def normalizeSeqDic(dic, norm_dic = {}, legend = ()):
'''returns a normalized dictionary from a seq_amp_dic. Normalization is performed using the first time point as reference
'''
try :
list_keys = dic.keys()
for key in list_keys:
next_legend = legend + (key,)
normalizeSeqDic(dic[key], norm_dic, next_legend)
except AttributeError:
# normalization
# unpack list
mk, ek, nk, tpk = legend
#assign values to amplitude dict
if mk not in norm_dic: norm_dic[mk] = {}
if ek not in norm_dic[mk]: norm_dic[mk][ek] = {}
if nk not in norm_dic[mk][ek]: norm_dic[mk][ek][nk] = {}
if tpk not in norm_dic[mk][ek][nk]: norm_dic[mk][ek][nk][tpk] = {}
new_array = []
for x in range(dic.shape[0]):
new_array.append(dic[x][1:]/dic[x][0])
new_array = asarray(new_array)
norm_dic[mk][ek][nk][tpk] = new_array
return norm_dic
def poolDic(dic):
'''returns a dic in which all the values are pooled, and root (mk) keys are fused
these pooled dics can later be combined into another dic
'''
pooled_dic = {}
for mk in dic.keys():
for ek in dic[mk].keys():
for nk in dic[mk][ek].keys():
for tpk in dic[mk][ek][nk].keys():
#assign values to amplitude dict
if ek not in pooled_dic: pooled_dic[ek] = {}
if nk not in pooled_dic[ek]: pooled_dic[ek][nk] = {}
if tpk not in pooled_dic[ek][nk]:
pooled_dic[ek][nk][tpk] = dic[mk][ek][nk][tpk]
else: pooled_dic[ek][nk][tpk]= vstack((pooled_dic[ek][nk][tpk], dic[mk][ek][nk][tpk]))
return pooled_dic
def timePointsDic(dic):
'''Determines the timepoints for each individual key at root
'''
tp_dic = {}
for mk in dic.keys():
tp_list = []
for rgk in dic[mk].keys():
tp_list.extend(dic[mk][rgk]['Neuropil'].keys())
tp_dic[mk]=tuple(sorted(list(set(tp_list))))
return tp_dic
对于某些操作,我发现除了展平字典之外别无他法:
def flattenDic(dic, label):
'''flattens a dic to produce a list of of tuples containing keys and 'label' values
'''
flat_list = []
for mk in dic.keys():
for rgk in dic[mk].keys():
for nk in dic[mk][rgk].keys():
for ik in dic[mk][rgk][nk].keys():
for ek in dic[mk][rgk][nk][ik].keys():
flat_list.append((mk, rgk, nk, ik, ek, dic[mk][rgk][nk][ik][ek][label])
return flat_list
def extractDataSequencePoints(flat_list, mk, nk, tp_list):
'''produces a list containing arrays of time point values
time_points is a list of the time points wished (can have 2 or 3 elements)
'''
nb_tp = len(tp_list)
# build tp_seq list
tp_seq = []
tp1, tp2, tp3 = [], [], []
if nk == 'Neuropil':
tp1.extend(x for x in flat_list if x[0]==mk and x[2] == 'Neuropil' and x[3] == tp_list[0])
tp2.extend(x for x in flat_list if x[0]==mk and x[2] == 'Neuropil'and x[3] == tp_list[1])
else:
tp1.extend(x for x in flat_list if x[0]==mk and x[2] != 'Neuropil'and x[3] == tp_list[0])
tp2.extend(x for x in flat_list if x[0]==mk and x[2] != 'Neuropil'and x[3] == tp_list[1])
if nb_tp == 3:
if nk == 'Neuropil':
tp3.extend(x for x in flat_list if x[0]==mk and x[2] == 'Neuropil'and x[3] == tp_list[2])
else:
tp3.extend(x for x in flat_list if x[0]==mk and x[2] != 'Neuropil'and x[3] == tp_list[2])
for x in tp1:
for y in tp2:
if x[0:3] == y[0:3] :
if nb_tp == 3:
for z in tp3:
if x[0:3] == z[0:3] :
tp_seq.append(asarray([x[4],y[4],z[4]]))
else:
tp_seq.append(asarray([x[4],y[4]]))
return tp_seq
【问题讨论】:
-
@AlexandreS:恐怕我对您的样本数据了解得不够多,无法提供很多建议。请您详细说明您正在分析的数据以及您正在执行的分析?
-
@MattH:我编辑了问题以提供更多详细信息。如果还不够,请告诉我
-
@AlexandrS:感谢您的澄清。如果您能解释目前如何获取/存储/派生这些数据,可能会有所帮助。我认为前进的道路是让您制作一个抽象图,将您的结构化为具有属性的对象以及对象/属性如何相互关联。当我决定如何编写数据结构时,我经常会勾勒出这些东西。
-
我不认为花在学习 OOP 和 SQL 上的时间被浪费到了死胡同。自学没什么不好。编码通常归结为为工作选择正确的工具。自学的一个特别困难是熟悉足够广泛的工具集。面向对象编程和提供结构化查询语言的数据库是现代编码工具集的重要组成部分,只有了解它们,您才会成为更好的编码人员。
-
我实际上是在开始编写分析例程代码之前勾画了数据结构,但我的部分问题是我缺乏足够的文化来了解哪些概念最适合我的需求。当然,学习 OOP 或 SQL 永远不会浪费。但是我需要优化我的学习路径,以便在我可以留出的有限时间内获得最好的收益来提高我的技能。希望通过借鉴其他人的经验,我可以限制我必须经历的试错次数。
标签: python dictionary nested