Thả các hàng có tất cả các số không trong khung dữ liệu gấu trúc


102

Tôi có thể sử dụng pandas dropna()chức năng để loại bỏ các hàng có một số hoặc tất cả các cột được đặt là NA's. Có một chức năng tương đương để giảm các hàng với tất cả các cột có giá trị 0 không?

P   kt  b   tt  mky depth
1   0   0   0   0   0
2   0   0   0   0   0
3   0   0   0   0   0
4   0   0   0   0   0
5   1.1 3   4.5 2.3 9.0

Trong ví dụ này, chúng tôi muốn loại bỏ 4 hàng đầu tiên khỏi khung dữ liệu.

cảm ơn!


Chỉ cần làm rõ, đây là hai câu hỏi. Một, để giảm các cột có tất cả các giá trị là 0. Nhưng ngoài ra, đối với một hàm tương đương với dropna () sẽ giảm các cột có bất kỳ giá trị nào là 0.
alchemy

Câu trả lời:


110

Hóa ra điều này có thể được thể hiện một cách độc đáo theo kiểu vectơ:

> df = pd.DataFrame({'a':[0,0,1,1], 'b':[0,1,0,1]})
> df = df[(df.T != 0).any()]
> df
   a  b
1  0  1
2  1  0
3  1  1

6
Nice, nhưng tôi nghĩ rằng bạn có thể tránh phủ định vớidf = df[(df.T != 0).any()]
Akavall

1
@Akavall Tốt hơn nhiều!
U2EF1

1
Chỉ cần lưu ý: OP muốn giảm rows with all columns having value 0, nhưng người ta có thể suy ra allphương pháp.
paulochf

1
Tất cả các câu trả lời này giải thích cách chúng ta có thể giảm các hàng có tất cả các số không, Tuy nhiên, tôi muốn giảm các hàng có số 0 trong cột đầu tiên. Với sự trợ giúp của tất cả các cuộc thảo luận và câu trả lời trong bài đăng này, tôi đã thực hiện điều này bằng cách thực hiện df.loc [df.iloc [:, 0]! = 0]. Chỉ muốn chia sẻ vì vấn đề này có liên quan đến câu hỏi này !!
hemanta 14/02/19

2
Phép chuyển vị không cần thiết, bất kỳ () nào cũng có thể lấy trục làm tham số. Vì vậy, tác phẩm này: df = df [df.any (trục = 1)]
Rahul Jha

129

Lót. Không cần chuyển vị:

df.loc[~(df==0).all(axis=1)]

Và đối với những người thích đối xứng, điều này cũng có tác dụng ...

df.loc[(df!=0).any(axis=1)]

1
Cho ngắn gọn (và, theo ý kiến của tôi, rõ ràng về mục đích) kết hợp này và bình luận Akavall của: df.loc[(df != 0).any(1)]. Làm việc theo nhóm!
Dan Allan

1
+1, chuyển vị nhanh hơn 30% - 491 đến 614 microec, và tôi thích axis=1nó rõ ràng; pythonic hơn trong quan điểm của tôi
gt6989b

Một số đề cập nên được tạo ra về sự khác biệt giữa việc sử dụng .all và .any vì câu hỏi ban đầu đã đề cập đến tính tương đương của dropna. Nếu bạn muốn bỏ tất cả các hàng có bất kỳ cột nào chứa số 0, bạn phải đảo ngược câu trả lời .all và .any ở trên. Phải mất một lúc tôi mới nhận ra điều này khi tôi đang tìm kiếm chức năng đó.
Zak Keirn

Điều này không làm việc cho tôi, nhưng lợi nhuận cho tôi chính xác cùngdf
Robvh

Có phiên bản 'thay thế' của cái này không? Tôi thấy rằng để giảm các hàng trong một df như OP yêu cầu, điều này sẽ cần phải df = df.loc[(df!=0).all(axis=1)]df = df.loc[(df!=0).any(axis=1)]để giảm các hàng có bất kỳ số 0 nào giống như thực tế tương đương với dropna ().
alchemy

19

Tôi tra cứu câu hỏi này khoảng một tháng một lần và luôn phải tìm ra câu trả lời hay nhất từ ​​các bình luận:

df.loc[(df!=0).any(1)]

Cảm ơn Dan Allan!


2
Không cần đào. @ 8one6 đã đưa điều này vào câu trả lời của anh ấy vào năm 2014, phần nói rằng: "Và dành cho những người thích sự đối xứng ...".
Rahul Murmuria 19/06/17

14

Thay thế các số không bằng nanvà sau đó thả các hàng với tất cả các mục nhập là nan. Sau đó thay thế nanbằng số không.

import numpy as np
df = df.replace(0, np.nan)
df = df.dropna(how='all', axis=0)
df = df.replace(np.nan, 0)

3
Điều này sẽ không thành công nếu bạn có bất kỳ NaN-s nào tồn tại từ trước trong dữ liệu.
OmerB


7

Một số giải pháp tôi thấy hữu ích khi tra cứu vấn đề này, đặc biệt là đối với các tập dữ liệu lớn hơn:

df[(df.sum(axis=1) != 0)]       # 30% faster 
df[df.values.sum(axis=1) != 0]  # 3X faster 

Tiếp tục với ví dụ từ @ U2EF1:

In [88]: df = pd.DataFrame({'a':[0,0,1,1], 'b':[0,1,0,1]})

In [91]: %timeit df[(df.T != 0).any()]
1000 loops, best of 3: 686 µs per loop

In [92]: df[(df.sum(axis=1) != 0)]
Out[92]: 
   a  b
1  0  1
2  1  0
3  1  1

In [95]: %timeit df[(df.sum(axis=1) != 0)]
1000 loops, best of 3: 495 µs per loop

In [96]: %timeit df[df.values.sum(axis=1) != 0]
1000 loops, best of 3: 217 µs per loop

Trên một tập dữ liệu lớn hơn:

In [119]: bdf = pd.DataFrame(np.random.randint(0,2,size=(10000,4)))

In [120]: %timeit bdf[(bdf.T != 0).any()]
1000 loops, best of 3: 1.63 ms per loop

In [121]: %timeit bdf[(bdf.sum(axis=1) != 0)]
1000 loops, best of 3: 1.09 ms per loop

In [122]: %timeit bdf[bdf.values.sum(axis=1) != 0]
1000 loops, best of 3: 517 µs per loop

Những điều tồi tệ có xảy ra nếu hàng của bạn chứa -1 và 1 không?
Rhys Ulerich

Tất nhiên, tổng sẽ không hoạt động nếu bạn có các hàng bằng nhau cộng lại bằng 0. Đây là một cách giải quyết nhanh chóng cho điều đó chỉ chậm hơn một chút: df[~(df.values.prod(axis=1) == 0) | ~(df.values.sum(axis=1)==0)]
clocker

Hàm prod () không giải quyết được bất cứ điều gì. Nếu bạn có bất kỳ số 0 nào trong hàng sẽ trả về 0. Nếu bạn phải xử lý một hàng như thế này: [-1, -0,5, 0, 0,5, 1], cả hai giải pháp của bạn sẽ không hoạt động.
Rahul Murmuria

Dưới đây là một phiên bản đúng mà làm việc 3x nhanh hơn so với câu trả lời được chấp nhận:bdf[np.square(bdf.values).sum(axis=1) != 0]
Rahul Murmuria

5
import pandas as pd

df = pd.DataFrame({'a' : [0,0,1], 'b' : [0,0,-1]})

temp = df.abs().sum(axis=1) == 0      
df = df.drop(temp)

Kết quả:

>>> df
   a  b
2  1 -1

Không phù hợp với tôi với khung dữ liệu 1 cột. GotValueError: labels [True ... ] not contained in matrix
The Unfun Cat

thay vì df = df.drop(temp)sử dụngdf = df.drop(df[temp].index)
Douglas Ferreira

3

Bạn có thể sử dụng một lambdahàm nhanh để kiểm tra xem tất cả các giá trị trong một hàng nhất định có phải là không 0. Sau đó, bạn có thể sử dụng kết quả của việc áp dụng điều đó lambdanhư một cách để chỉ chọn các hàng phù hợp hoặc không khớp với điều kiện đó:

import pandas as pd
import numpy as np

np.random.seed(0)

df = pd.DataFrame(np.random.randn(5,3), 
                  index=['one', 'two', 'three', 'four', 'five'],
                  columns=list('abc'))

df.loc[['one', 'three']] = 0

print df
print df.loc[~df.apply(lambda row: (row==0).all(), axis=1)]

Sản lượng:

              a         b         c
one    0.000000  0.000000  0.000000
two    2.240893  1.867558 -0.977278
three  0.000000  0.000000  0.000000
four   0.410599  0.144044  1.454274
five   0.761038  0.121675  0.443863

[5 rows x 3 columns]
             a         b         c
two   2.240893  1.867558 -0.977278
four  0.410599  0.144044  1.454274
five  0.761038  0.121675  0.443863

[3 rows x 3 columns]

1

Một thay thế khác:

# Is there anything in this row non-zero?
# df != 0 --> which entries are non-zero? T/F
# (df != 0).any(axis=1) --> are there 'any' entries non-zero row-wise? T/F of rows that return true to this statement.
# df.loc[all_zero_mask,:] --> mask your rows to only show the rows which contained a non-zero entry.
# df.shape to confirm a subset.

all_zero_mask=(df != 0).any(axis=1) # Is there anything in this row non-zero?
df.loc[all_zero_mask,:].shape

0

Đối với tôi mã này: df.loc[(df!=0).any(axis=0)] không hoạt động. Nó trả về tập dữ liệu chính xác.

Thay vào đó, tôi đã sử dụng df.loc[:, (df!=0).any(axis=0)]và bỏ tất cả các cột có giá trị 0 trong tập dữ liệu

Hàm đã loại bỏ .all()tất cả các cột có bất kỳ giá trị 0 nào trong tập dữ liệu của tôi.


-1
df = df [~( df [ ['kt'  'b'   'tt'  'mky' 'depth', ] ] == 0).all(axis=1) ]

Hãy thử lệnh này hoạt động hoàn hảo.


-2

Để bỏ tất cả các cột có giá trị 0 vào bất kỳ hàng nào:

new_df = df[df.loc[:]!=0].dropna()
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.