2014-10-28 48 views
12

Tôi có một dataframe (bằng Python 2.7, gấu trúc 0.15.0):gấu trúc Python áp dụng chức năng nếu một giá trị cột không phải là NULL

df= 
     A B    C 
0 NaN 11    NaN 
1 two NaN ['foo', 'bar'] 
2 three 33    NaN 

Tôi muốn áp dụng một chức năng đơn giản cho các hàng mà không chứa NULL các giá trị trong một cột cụ thể. chức năng của tôi cũng đơn giản càng tốt:

def my_func(row): 
    print row 

Và áp dụng mã của tôi là như sau:

df[['A','B']].apply(lambda x: my_func(x) if(pd.notnull(x[0])) else x, axis = 1) 

Nó hoạt động một cách hoàn hảo. Nếu tôi muốn kiểm tra cột 'B' cho các giá trị NULL, thì pd.notnull() cũng hoạt động hoàn hảo. Nhưng nếu tôi chọn cột 'C' có chứa đối tượng danh sách:

df[['A','C']].apply(lambda x: my_func(x) if(pd.notnull(x[1])) else x, axis = 1) 

sau đó tôi nhận được thông báo lỗi sau: ValueError: ('The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()', u'occurred at index 1')

Có ai biết tại sao pd.notnull() chỉ hoạt động đối với các cột số nguyên và chuỗi nhưng không cho 'danh sách cột'?

Và đó là một cách đẹp hơn để kiểm tra các giá trị NULL trong cột 'C' thay vì điều này:

df[['A','C']].apply(lambda x: my_func(x) if(str(x[1]) != 'nan') else x, axis = 1) 

Cảm ơn bạn!

Trả lời

12

Vấn đề là pd.notnull(['foo', 'bar']) hoạt động theo nguyên tắc và trả về array([ True, True], dtype=bool). Nếu điều kiện của bạn trys để chuyển đổi đó để một boolean, và đó là khi bạn nhận được ngoại lệ.

Để khắc phục nó, bạn chỉ có thể quấn tuyên bố ISNULL với np.all:

df[['A','C']].apply(lambda x: my_func(x) if(np.all(pd.notnull(x[1]))) else x, axis = 1) 

Bây giờ bạn sẽ thấy rằng np.all(pd.notnull(['foo', 'bar'])) thực True là.

+0

lưu ý rằng 'np.all ([True, True])' sẽ trả về 'True'. Tôi nghĩ rằng sẽ làm việc cho OP. –

+0

@PaulH Cảm ơn. Tôi đã thử với 'all' nhưng bị bỏ quên' np.all'. Vấn đề không phải là với '[True, True]', mà là với 'False'. Trong khi 'tất cả (pd.notnull (None))' gây ra lỗi, 'np.all (pd.notnull (None))' thì không. – Korem

+0

Cảm ơn bạn Korem, nó hoạt động! Những gì tôi tự hỏi là một 'pd.notnull đơn (df ['C'])' trả về với 'False, True, False' nhưng không phải với' False, [True, True], False'. – ragesz

4

Cũng một cách khác là chỉ cần sử dụng row.notnull().all() (không numpy), đây là một ví dụ:

df.apply(lambda row: func1(row) if row.notnull().all() else func2(row), axis=1) 

Đây là một ví dụ hoàn chỉnh về df của bạn:

>>> d = {'A': [None, 2, 3, 4], 'B': [11, None, 33, 4], 'C': [None, ['a','b'], None, 4]} 
>>> df = pd.DataFrame(d) 
>>> df 
    A  B  C 
0 NaN 11.0 None 
1 2.0 NaN [a, b] 
2 3.0 33.0 None 
3 4.0 4.0  4 
>>> def func1(r): 
...  return 'No' 
... 
>>> def func2(r): 
...  return 'Yes' 
... 
>>> df.apply(lambda row: func1(row) if row.notnull().all() else func2(row), axis=1) 
0 Yes 
1 Yes 
2 Yes 
3  No 

Và một ảnh chụp màn hình thân thiện hơn: -)

enter image description here

0

Tôi có một cột chứa danh sách và NaN s. Vì vậy, người tiếp theo làm việc cho tôi.

df.C.map(lambda x: my_func(x) if type(x) == list else x) 
+0

Các giải pháp tốt hơn đã được đưa ra. –

Các vấn đề liên quan