Python:字典键值与panda值的平均值
我有一个相当复杂的数据结构,即panda数据框架中的字典。假设我有这个数据帧Python:字典键值与panda值的平均值,python,python-3.x,pandas,dictionary,median,Python,Python 3.x,Pandas,Dictionary,Median,我有一个相当复杂的数据结构,即panda数据框架中的字典。假设我有这个数据帧 trials_ = [1,2,1,2] stimul_ = [1,1,2,2] data_ = [[{'peak_voltage': [30.5, 65], 'Spikecount': [2]}], [{'peak_voltage': [30.5, 65, 30], 'Spikecount': [3]}], [{'peak_voltage': [20.1], 'Spikecount': [1]}], 'NaN'] fe
trials_ = [1,2,1,2]
stimul_ = [1,1,2,2]
data_ = [[{'peak_voltage': [30.5, 65], 'Spikecount': [2]}], [{'peak_voltage': [30.5, 65, 30], 'Spikecount': [3]}], [{'peak_voltage': [20.1], 'Spikecount': [1]}], 'NaN']
featve = pd.DataFrame({'trial': trials_, 'stimulus': stimul_, 'data': data_})
featve
data stimulus trial
0 [{'peak_voltage': [30.5, 65], 'Spikecount': [2]}] 1 1
1 [{'peak_voltage': [30.5, 65, 30], 'Spikecount'... 1 2
2 [{'peak_voltage': [20.1], 'Spikecount': [1]}] 2 1
3 NaN 2 2
dict_data = defaultdict(list)
for idx in range(len(data_)):
if isinstance(data_[idx], list):
for sub in data_[idx]:
repeats = len(sub['peak_voltage'])
data_dict['peak_voltage'] += sub['peak_voltage']
data_dict['Spikecount'] += sub['Spikecount'] * repeats
data_dict['trial'] += [trials_[idx]] * repeats
data_dict['stimulus'] += [stimul_[idx]] * repeats
else:
data_dict['peak_voltage'].append('NaN')
data_dict['Spikecount'].append('NaN')
data_dict['trial'] += [trials_[idx]]
data_dict['stimulus'] += [stimul_[idx]]
pd.DataFrame(data_dict)
Spikecount peak_voltage stimulus trial
0 2 30.5 1 1
1 2 65 1 1
2 3 30.5 1 2
3 3 65 1 2
4 3 30 1 2
5 1 20.1 2 1
6 NaN NaN 2 2
现在,我想在我的“数据”列(这里是峰值电压和峰值计数)中计算我字典中每个关键元素在所有试验中的中位数和25%/75%四分位数
中位数的一个例子:
我想要在所有试验[30.5,65,20.1]>30.5中应用刺激1时的中值峰值电压值。当应用刺激2时,情况相同[30.5,65,30,NaN]>30.5。当然,穗数也是如此
老实说,我不知道从哪里开始。如果我只想计算中位数而不考虑simulus,我只需要使用
featve.data.median
但这不是我想要的。另外,如果我没有字典,只有数字,我会用类似的东西
featve.groupby('stimulus').data.apply(np.nanmedian)
但在熊猫桌上放着字典的情况下,我能做些什么呢
编辑1
我有10个刺激,每个16个试验,总共160行。字典是一个工具箱的输出,我用它来查找我的数据轨迹的某些特征(例如神经元动作电位峰值的时间)。我决定在一个熊猫数据框中组织生成的160个词典,以便同时跟踪数据、刺激和试验。首先,我不知道这是否不幸。对于您提出的问题,我建议您重新构建数据帧。而不是使用以下内容构建
featve
:
data_ = [[{'peak_voltage': [30.5, 65], 'Spikecount': [2]}], [{'peak_voltage': [30.5, 65, 30], 'Spikecount': [3]}], [{'peak_voltage': [20.1], 'Spikecount': [1]}], 'NaN']
data_ = {'peak_voltage': [30.5, 65, 30.5, 65, 30, 20.1, np.nan], 'Spikecount': [2,2,3,3,3,1, np.nan], 'trials': [1,1,2,2,2,1,2], 'stimulus': [1,1,1,1,1,2,2]}
featve = pd.DataFrame(data_)
结果是以下数据帧:
Spikecount peak_voltage stimulus trials
0 2.0 30.5 1 1
1 2.0 65.0 1 1
2 3.0 30.5 1 2
3 3.0 65.0 1 2
4 3.0 30.0 1 2
5 1.0 20.1 2 1
6 NaN NaN 2 2
在这个数据帧上,您可以像平常一样对中位数进行分组和计算
e、 g
更新
我理解人们对没有“好”数据的担忧。给定一个遵循数据
格式的严格构造,您可以使用它来获得更好的数据帧
trials_ = [1,2,1,2]
stimul_ = [1,1,2,2]
data_ = [[{'peak_voltage': [30.5, 65], 'Spikecount': [2]}], [{'peak_voltage': [30.5, 65, 30], 'Spikecount': [3]}], [{'peak_voltage': [20.1], 'Spikecount': [1]}], 'NaN']
featve = pd.DataFrame({'trial': trials_, 'stimulus': stimul_, 'data': data_})
featve
data stimulus trial
0 [{'peak_voltage': [30.5, 65], 'Spikecount': [2]}] 1 1
1 [{'peak_voltage': [30.5, 65, 30], 'Spikecount'... 1 2
2 [{'peak_voltage': [20.1], 'Spikecount': [1]}] 2 1
3 NaN 2 2
dict_data = defaultdict(list)
for idx in range(len(data_)):
if isinstance(data_[idx], list):
for sub in data_[idx]:
repeats = len(sub['peak_voltage'])
data_dict['peak_voltage'] += sub['peak_voltage']
data_dict['Spikecount'] += sub['Spikecount'] * repeats
data_dict['trial'] += [trials_[idx]] * repeats
data_dict['stimulus'] += [stimul_[idx]] * repeats
else:
data_dict['peak_voltage'].append('NaN')
data_dict['Spikecount'].append('NaN')
data_dict['trial'] += [trials_[idx]]
data_dict['stimulus'] += [stimul_[idx]]
pd.DataFrame(data_dict)
Spikecount peak_voltage stimulus trial
0 2 30.5 1 1
1 2 65 1 1
2 3 30.5 1 2
3 3 65 1 2
4 3 30 1 2
5 1 20.1 2 1
6 NaN NaN 2 2
首先,我不知道你为什么要把你的字典放在列表中,但我建议你的数据有一个没有它们的版本。另外,如果您的大多数数据都是以字典的形式存在,那么我建议您也将缺少的数据以字典的形式存在。一旦这样做,您就可以将
数据
放入数据帧中。所以
my_data=pd.DataFrame([{'peak_voltage':[30.5,65],'Spikecount':[2]},{'peak_voltage':[30.5,65,30],'Spikecount':[3]},{'peak_voltage':[20.1],'Spikecount':[1]},{/code>
然后,您可以有一个数据帧,即刺激
和试验
:
stimulus\u-trial\u-df=pd.DataFrame({'trial':trials,'stimul':stimul})
接下来,您可以在stiumlus\u-trial\u-df的属性上切片my\u数据
:
subset1=my\u data.loc[stimulation\u trial\u df['stimulation']==1]
注意,您必须确保您的两个数据帧具有一致的索引,这样才能工作
一旦有了subset1
,就可以展平其中的列:
spikecount\u agg=[subset1行的spikecount['spikecount']行的spikecount]
最后,可以对展平列执行任何操作:
import statistics
current_median = statistics.median(spikecount_agg)
最后一点注意:您在问题中输入了[30.5,65,20.1]->30.5
,但您的数据有两份30.5
和65
。在这种特殊情况下,这不会改变中间值,但您应该考虑是否要考虑数据中的多个副本。我的代码包含它们,因此如果您不需要它们,您必须调整代码
编辑:
关于不同刺激的子集,一个for循环就足够了。如果你有一个包含独特刺激的物体,你可以在上面循环;如果您没有,您可以使用unique\u stimuli=set(stimul\u)
生成它:
你的答案是假设数据是“好”的形式:每行的峰值计数和峰值电压的多重性是相同的,等等?你的答案将数据放在一种比我的答案在许多方面更干净的形式,但它不太一般。如果OP只是处理呈现的数据,他们可以一字不差地复制您的答案,但如果他们获得更多数据,调整您的答案将非常重要(调整我的答案可能也很重要,但可能不那么重要)。您可能希望提供将OP数据转换为表单的代码,而不仅仅是手动转换。谢谢您的输入!我正在使用一个名为EFEL()的工具箱来提取数据跟踪的特定特征。输出是一个字典,如我的示例所示。我总共做了160次(10次刺激,每次16次试验),并将所有字典存储在熊猫数据框中,如上图所示。这意味着字典结构是给定的。所以我需要以不同的方式解决这个问题,或者以某种方式重建我的字典。@accumulation你提出了一个合理的担忧。我更新了答案,以解决加载不太好数据的更一般情况。谢谢您的想法!我使用列表是因为python会抛出ValueError:与Series不兼容的索引器。我将字典放在for循环中的数据帧中。无论如何我是否正确理解您的解决方案,即我需要为每个刺激集手动创建子集?那会很累,因为我有10个刺激(也许我应该在我的帖子中提到,我会编辑它)。关于你的最后一个注释:我在上面的例子中使用了任意数字。但是如果我的数据中有两个相同的数字,我会考虑两者。所以很高兴您已经包含了它们。@Svenno-Nito:您可以在子集代码中放入一个变量,而不是一个固定值。我编辑了我的答案来澄清。您还可以在for循环中执行for循环,在[25,50,75]
中对p循环p,然后取pth百分位。