按单元格中包含的列表成员选择行

时间:2014-07-18 12:39:51

标签: python pandas selection dataframe

在我的数据框中,我有一个包含项目列表的列。我想只选择那些包含所有或几个项目的行。至少匹配一个列表会很棒。

import pandas as pd
df = pd.DataFrame([[2,[2,3,8]]], columns=['a','b'])
df

我尝试了以下内容:

 df[df['b'] == [2,3,8]]
 df[[2,3,8] in df['b']] # and etc.

我觉得被蒙住眼睛......

到FooBar:

我正在进行科学领域分析。该列表包含不同科学领域的代码。行代表案例,当这些科学领域是共同的时候。我可以将列表成员保留在不同的列中,但问题是coocuring字段的数量正在发生变化。因此我认为将列表保存在单元格中是可以的。

3 个答案:

答案 0 :(得分:2)

我认为你可以做到以下几点:

idx = []

S = [2,3,8]

for i, line in df.iterrows():
     if set(S).issubset(line['b']):
           idx.append(i)

现在,您只能选择您感兴趣的行:

df_subset = df.ix[idx]

答案 1 :(得分:1)

比较元组没有问题

import pandas as pd

data = [
    [1, (2,3,8)],
    [2, (12,13,18)],
    [3, (2,3,8)],
    [4, (1,2,3,8,10)],
    [5, (8,3,2)],
]

#----------------------------------------------

df_tuple = pd.DataFrame( data, columns=['a','b'])

print '\n DataFrame with tuples \n'
print df_tuple

print '\n tuple == : \n'

print df_tuple['b'] == (2,3,8)
print df_tuple[ df_tuple['b'] == (2,3,8) ]

print '\n tuple eq() : \n'

print df_tuple['b'].eq((2,3,8))
print df_tuple[ df_tuple['b'].eq((2,3,8)) ]

#----------------------------------------------

结果

 DataFrame with tuples 

   a                 b
0  1         (2, 3, 8)
1  2      (12, 13, 18)
2  3         (2, 3, 8)
3  4  (1, 2, 3, 8, 10)
4  5         (8, 3, 2)

 tuple == : 

0     True
1    False
2     True
3    False
4    False
Name: b, dtype: bool
   a          b
0  1  (2, 3, 8)
2  3  (2, 3, 8)

 tuple eq() : 

0     True
1    False
2     True
3    False
4    False
Name: b, dtype: bool
   a          b
0  1  (2, 3, 8)
2  3  (2, 3, 8)

但是比较列表存在问题,我不知道为什么。

但是您需要包含列表[2,3,8]中所有或多个项目的行,因此我会将apply()与自己的函数一起使用。

import pandas as pd

#----------------------------------------------

data = [
    [1, [2,3,8]],
    [2, [12,13,18]],
    [3, [2,3,8]],
    [4, [1,2,3,8,10]],
    [5, [8,3,2]],
]

#----------------------------------------------

df_list = pd.DataFrame( data, columns=['a','b'])

print '\n DataFrame with lists \n'
print df_list

print '\n test: \n'

# test if any element from data list is in [2,3,8]
def test(data):
    return any( x in [2,3,8] for x in data )

print df_list['b'].apply(test)
print df_list[ df_list['b'].apply(test) ]

#----------------------------------------------

结果

 DataFrame with lists 

   a                 b
0  1         [2, 3, 8]
1  2      [12, 13, 18]
2  3         [2, 3, 8]
3  4  [1, 2, 3, 8, 10]
4  5         [8, 3, 2]

 test: 

0     True
1    False
2     True
3     True
4     True
Name: b, dtype: bool
   a                 b
0  1         [2, 3, 8]
2  3         [2, 3, 8]
3  4  [1, 2, 3, 8, 10]
4  5         [8, 3, 2]

更有用的版本 - 第二个参数:

test_any如果 数据列表中的任何元素位于预期列表

,则返回True
def test_any(data, expected):
    return any( x in expected for x in data )

print df_list['b'].apply(lambda x:test_any(x,[2,3,8]) )
print df_list[ df_list['b'].apply(lambda x:test_any(x,[2,3,8]) ) ]
如果数据列表中的所有元素都在预期列表

,则

test_all返回True

def test_all(data, expected):
    return all( x in expected for x in data )

print df_list['b'].apply(lambda x:test_all(x,[2,3,8]) )
print df_list[ df_list['b'].apply(lambda x:test_all(x,[2,3,8]) ) ]

您可以交换'x'和[2,3,8]

如果预期列表中的任何元素位于数据列表

,则

获取True

print df_list[ df_list['b'].apply(lambda x:test_any_2([2,3,8], x) ) ]
如果预期列表中所有元素位于数据列表

,则

获取True

print df_list[ df_list['b'].apply(lambda x:test_all_2([2,3,8], x) ) ]

答案 2 :(得分:1)

好吧,我执行以下操作以使您的数据帧更好地使用#34;格式。我允许任何数量的"科学属性",如你所说,并将其称为"其他"。

D = df
df = pd.concat([D['a'], pd.DataFrame(D['b'].tolist(), index=D.index)], axis=1, keys=['standard', 'additional'])
In[103]: df
Out[103]: 
   standard  additional      
          a           0  1  2
0         2           2  3  8

现在我们只搜索"其他"你给我们的钥匙的一部分:

In[133]: any(df['additional'] == 3, axis=1) & any(df['additional'] == 8, axis=1)
Out[133]: array([ True], dtype=bool)

现在我只是破解了第二条假行,检查我是否真的"没有选择"那些不符合标准的人:

df2 = df.append(df)
df2.iloc[1] += 1
any(df2['additional'] == 3, axis=1) & any(df2['additional'] == 8, axis=1)
Out[132]: array([ True, False], dtype=bool)

确认: 我从HYRY here了解到concat()的可爱利用率。