2016-05-31 74 views
0

我有基于多个输入收集的测试数据,并生成单个输出。我正在将这些数据存储在一个字典中,其中的键是我的参数/结果标签,其值是测试条件和结果。我希望能够过滤数据,以便可以基于孤立的条件生成图。包含列表数据的字典,基于列表中的值的过滤器

在我的例子中,我的测试条件是'a'和'b',实验的结果是'c'。我想过滤我的数据,所以我得到一个具有相同关键字,值结构的字典,只有我的过滤结果。然而,我目前的字典理解返回一个空的字典。任何建议,以获得理想的结果?

目前代码:

data = {'a': [0, 1, 2, 0, 1, 2], 'b': [10, 10, 10, 20, 20, 20], 'c': [1.3, 1.9, 2.3, 2.3, 2.9, 3.4]} 
filtered_data = {k:v for k,v in data.iteritems() if v in data['b'] >= 20} 

所需的结果:

{'a': [0, 1, 2], 'b': [20, 20, 20], 'c': [2.3, 2.9, 3.4]} 

当前结果:

{} 

而且,是本词典列出的一个很好的模式来存储这类数据,因为我要过滤结果,还是有更好的方法来实现这一目标?

+1

@SilentMonk,不,它看起来对我来说,他希望继续在项目'了'和' c''''b''中的对应项目是'= 20' –

+0

你是条件> = 20意味着首先键'a'将永远不会有值和'c',因为该列表中没有值那符合你的条件 – reticentroot

+0

@IanMcLaird,明白了。所以我删除了评论。但是你已经回复了。抱歉。 – SilentMonk

回答

3

使用本:

k:[v[i] for i,x in enumerate(v) if data['b'][i] >= 20] for k,v in data.items()} 

所需的结果:

{'a': [0, 1, 2], 'c': [2.3, 2.9, 3.4], 'b': [20, 20, 20]} 
+0

谢谢你的回答,但我想要的数据不一定限于'b'中的最后三个值。例如,我可以过滤并获得'a'= 1的所有值。 –

+0

我更新了代码:这是否解决了您的问题 –

+0

这样做,这似乎是不使用熊猫的最佳解决方案。 –

3

考虑在这类工作中使用熊猫模块。

import pandas as pd 
df = pd.DataFrame(data) 
df = df[df["b"] >= 20] 
print(df) 

看起来像这样会给你你想要的。您正在使用字典键来表示列名称,并且这些值只是给定列中的行,因此它可以使用数据框。

结果:

a b c 
3 0 20 2.3 
4 1 20 2.9 
5 2 20 3.4 
+1

如果您想重置行索引,请在过滤器下方添加以下内容: 'df.reset_index(drop = True)' –

+0

我以前没有使用过熊猫,我会研究一下。谢谢。 –

0

是否所有匹配订单字典值列表?如果是这样,你可以看看你想要过滤的列表,例如'b',在这种情况下,找到你想要的值,然后在字典中的其他值上使用这些索引或相同的片。

例如:

matching_indices = [] 
for i in data['b']: 
    if data['b'][i] >= 20: 
     matching_indices.append(i) 
new_dict = {} 
for key in data: 
    for item in matching_indices: 
     new_dict[key] = data[key][item] 

你也许可以推测它的字典理解,如果你想要的。希望这很清楚。

+0

是的,我所有的价值观都是按顺序排列的。如果我在使用MATLAB(我的母语)工作,这是我会采用的路线,但是我尝试使用理解,因为它们看起来更加高效和pythonic。如果我无法实现这个目标,我将回到迭代循环。谢谢你的帮助。 –

0

你可以改变这种方法,它会给它更多的灵活性。您当前的逻辑意味着,数据集A和C被忽视,因为没有值大于或等于20:

data = {'a': [0, 1, 2, 0, 1, 2], 'b': [10, 10, 10, 20, 20, 20], 'c': [1.3, 1.9, 2.3, 2.3, 2.9, 3.4]} 
filter_vals = ['a', 'b'] 
new_d = {} 
for k, v in data.iteritems(): 
    if k in filter_vals: 
    new_d[k] = [i for i in v if i >= 20] 

print new_d 

现在我不是一个大风扇,如果很多if语句,但这样的事情是直线前进并且可以调用多次

def my_filter(operator, condition, filter_vals, my_dict): 
    new_d = {} 
    for k, v in my_dict.iteritems(): 
    if k in filter_vals: 
     if operator == '>': 
     new_d[k] = [i for i in v if i > condition] 
     elif operator == '<': 
     new_d[k] = [i for i in v if i < condition] 
     elif operator == '<=': 
     new_d[k] = [i for i in v if i <= condition] 
     elif operator == '>=': 
     new_d[k] = [i for i in v if i >= condition] 
    return new_d 
+0

谢谢@reticentroot,来自coralv的回答相同的评论:这是如果我在MATLAB(我的母语)工作,我会采取的路线,但我试图与理解工作,因为他们看起来更有效和pythonic。如果我无法实现这个目标,我将回到迭代循环。 –

+0

然后大熊猫可能是你最好的选择@Michael Lampe – reticentroot

0

我同意上面的熊猫方法。

如果由于某种原因,你讨厌大熊猫或是一位老学校的计算机科学家,元组是一种很好的方法来关联关系数据。在你的例子中,a,b和c列表是列而不是行。对于元组,你会希望保存为行:

data = {'a':(0,10,1.3),'b':(1,10,1.9),'c':(2,10,2.3),'d':(0,20,2.3),'e':(1,20,2.9),'f':(2,20,3.4)} 

其中,元组存储在(条件1,条件2,结果)格式,你描述的,你可以调用单个测试或过滤为您介绍一套。从那里,你可以得到一个过滤的结果如下:

filtered_data = {k:v for k,v in data.iteritems() if v[1]>=20} 

返回:

{'d': (0, 20, 2.3), 'e': (1, 20, 2.9), 'f': (2, 20, 3.4)} 
+0

感谢您的回答。如果我走这条路线(使用行而不是列),那么我失去了我的列标题(dict键),所以我可以使用列表并按照您的建议过滤。这是一个选项,但我希望保留我的数据传输/自我标签的列标题。 –

相关问题