2014-07-18 45 views
0

在我的數據框中,我有一個包含項目列表的列。我想只選擇那些包含全部或幾個項目的行。至少匹配一個列表會很好。通過單元格中包含的列表成員選擇行

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的:

我做科學領域的分析。該列表包含不同科學領域的代碼。哪裏的行代表案例,什麼時候這些科學領域正在合作。我可以將列表成員保留在不同的列中,但問題在於協同合作領域的數量正在發生變化。因此,我認爲可以在單元格中保留一個列表。

+1

此設置(將列表作爲單個列)不是標準的,並且有許多缺點。你是否知道這個決定的利弊,並有意設置你的數據庫?如果沒有,分享更多關於您的最終目標或您試圖組織什麼樣的數據,並且我們可能會建議更好的數據庫策略。 – FooBar

+0

(你可以通過複雜的答案來看到設置的尷尬 - 通常應該是小菜一碟) – FooBar

+1

@FooBar你是對的 - 一個單元中的許多元素是書中描述的'antipattern'之一[SQL反模式](http://www.amazon.com/SQL-Apatpatterns-Programming-Pragmatic-Programmers/dp/1934356557) – furas

回答

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_anyTrue如果任何元素從數據名單上預計列表

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

我認爲你可以做到以下幾點:

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] 
+0

+ set for set()' - 我總是忘記它是多麼有用。 – furas

+1

@Aidis你可以用更簡單的方式使用它:'df [df ['b']。apply(lambda x:set(x).issubset([2,3,8]))]'或者用'swap''x'和'[2,3,8]''df [df ['b']。apply(lambda x:set([2,3,8])。issubset(x))]'' – furas

1

好吧,我這樣做,讓您的數據幀爲「更好「的格式。我允許任何數量的「科學屬性」,就像你打電話給他們的那樣,並且將它們稱爲「額外的」。

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

相關問題