Thả các hàng chứa các ô trống từ DataFrame của gấu trúc


87

Tôi có một pd.DataFramecái được tạo bằng cách phân tích cú pháp một số bảng tính excel. Một cột trong đó có các ô trống. Ví dụ: dưới đây là đầu ra cho tần suất của cột đó, 32320 bản ghi có giá trị bị thiếu cho Người thuê .

>>> value_counts(Tenant, normalize=False)
                              32320
    Thunderhead                8170
    Big Data Others            5700
    Cloud Cruiser              5700
    Partnerpedia               5700
    Comcast                    5700
    SDP                        5700
    Agora                      5700
    dtype: int64

Tôi đang cố gắng bỏ các hàng bị thiếu Người thuê, tuy nhiên .isnull()tùy chọn không nhận ra các giá trị bị thiếu.

>>> df['Tenant'].isnull().sum()
    0

Cột có kiểu dữ liệu "Đối tượng". Điều gì đang xảy ra trong trường hợp này? Làm cách nào tôi có thể bỏ hồ sơ khi Người thuê bị thiếu?

Câu trả lời:


174

Gấu trúc sẽ nhận ra một giá trị là null nếu nó là một np.nanđối tượng, giá trị này sẽ in như NaNtrong DataFrame. Các giá trị bị thiếu của bạn có thể là các chuỗi trống, mà Gấu trúc không nhận ra là rỗng. Để khắc phục điều này, bạn có thể chuyển đổi các ô trống (hoặc bất kỳ ô trống nào trong ô trống của bạn) thành np.nancác đối tượng sử dụng replace(), sau đó gọi dropna()DataFrame của bạn để xóa các hàng có đối tượng thuê rỗng.

Để chứng minh, chúng tôi tạo một DataFrame với một số giá trị ngẫu nhiên và một số chuỗi trống trong một Tenantscột:

>>> import pandas as pd
>>> import numpy as np
>>> 
>>> df = pd.DataFrame(np.random.randn(10, 2), columns=list('AB'))
>>> df['Tenant'] = np.random.choice(['Babar', 'Rataxes', ''], 10)
>>> print df

          A         B   Tenant
0 -0.588412 -1.179306    Babar
1 -0.008562  0.725239         
2  0.282146  0.421721  Rataxes
3  0.627611 -0.661126    Babar
4  0.805304 -0.834214         
5 -0.514568  1.890647    Babar
6 -1.188436  0.294792  Rataxes
7  1.471766 -0.267807    Babar
8 -1.730745  1.358165  Rataxes
9  0.066946  0.375640         

Bây giờ chúng ta thay thế bất kỳ chuỗi trống nào trong Tenantscột bằng np.nancác đối tượng, như sau:

>>> df['Tenant'].replace('', np.nan, inplace=True)
>>> print df

          A         B   Tenant
0 -0.588412 -1.179306    Babar
1 -0.008562  0.725239      NaN
2  0.282146  0.421721  Rataxes
3  0.627611 -0.661126    Babar
4  0.805304 -0.834214      NaN
5 -0.514568  1.890647    Babar
6 -1.188436  0.294792  Rataxes
7  1.471766 -0.267807    Babar
8 -1.730745  1.358165  Rataxes
9  0.066946  0.375640      NaN

Bây giờ chúng ta có thể bỏ các giá trị null:

>>> df.dropna(subset=['Tenant'], inplace=True)
>>> print df

          A         B   Tenant
0 -0.588412 -1.179306    Babar
2  0.282146  0.421721  Rataxes
3  0.627611 -0.661126    Babar
5 -0.514568  1.890647    Babar
6 -1.188436  0.294792  Rataxes
7  1.471766 -0.267807    Babar
8 -1.730745  1.358165  Rataxes

Cảm ơn rất nhiều, tôi sẽ thử và lấy lại!
Amrita Sawant

2
@mcmath, hơi tò mò. Tại sao bạn nhập numpy và sử dụng np.nankhi bạn có thể làm được pd.np.nan?
propjk007

3
@ propjk007, cũng như nhiều việc trong cuộc sống, có nhiều cách để làm nhiều việc
andrew

Từ tôi kiểm tra , có vẻ như làm df[df['Tenant'].astype(bool)](giả sử không có ký tự khoảng trắng - chỉ chuỗi rỗng) là nhanh hơndf.replace('', np.nan).dropna(subset=['Tenant'])
cs95

43

Pythonic + Pand Lovely: df[df['col'].astype(bool)]

Các chuỗi trống là sai, có nghĩa là bạn có thể lọc các giá trị bool như sau:

df = pd.DataFrame({
    'A': range(5),
    'B': ['foo', '', 'bar', '', 'xyz']
})
df
   A    B
0  0  foo
1  1     
2  2  bar
3  3     
4  4  xyz
df['B'].astype(bool)                                                                                                                      
0     True
1    False
2     True
3    False
4     True
Name: B, dtype: bool

df[df['B'].astype(bool)]                                                                                                                  
   A    B
0  0  foo
2  2  bar
4  4  xyz

Nếu mục tiêu của bạn là xóa không chỉ các chuỗi trống mà còn cả các chuỗi chỉ chứa khoảng trắng, hãy sử dụng str.striptrước:

df[df['B'].str.strip().astype(bool)]
   A    B
0  0  foo
2  2  bar
4  4  xyz

Nhanh hơn bạn nghĩ

.astypelà một hoạt động được vectorised, điều này nhanh hơn mọi tùy chọn được trình bày cho đến nay. Ít nhất, từ các thử nghiệm của tôi. YMMV.

Đây là một so sánh thời gian, tôi đã đưa ra một số phương pháp khác mà tôi có thể nghĩ ra.

nhập mô tả hình ảnh ở đây

Mã điểm chuẩn, để tham khảo:

import pandas as pd
import perfplot

df1 = pd.DataFrame({
    'A': range(5),
    'B': ['foo', '', 'bar', '', 'xyz']
})

perfplot.show(
    setup=lambda n: pd.concat([df1] * n, ignore_index=True),
    kernels=[
        lambda df: df[df['B'].astype(bool)],
        lambda df: df[df['B'] != ''],
        lambda df: df[df['B'].replace('', np.nan).notna()],  # optimized 1-col
        lambda df: df.replace({'B': {'': np.nan}}).dropna(subset=['B']),  
    ],
    labels=['astype', "!= ''", "replace + notna", "replace + dropna", ],
    n_range=[2**k for k in range(1, 15)],
    xlabel='N',
    logx=True,
    logy=True,
    equality_check=pd.DataFrame.equals)

33

value_counts bỏ qua NaN theo mặc định, vì vậy rất có thể bạn đang xử lý "".

Vì vậy, bạn chỉ có thể lọc chúng ra như

filter = df["Tenant"] != ""
dfNew = df[filter]

1
Giải pháp @Bobs không hoạt động với tôi. df.dropna (subset = ['tenant'], inplace = True) hoạt động.
Amrita Sawant,

1
Xin lỗi vì điều đó. Tôi nghĩ bạn đang xử lý "" s. Bạn nên đăng giải pháp của mình dưới dạng câu trả lời
Bob Haffner

8

Có trường hợp ô có khoảng trắng, bạn không thể nhìn thấy nó, hãy sử dụng

df['col'].replace('  ', np.nan, inplace=True)

để thay thế khoảng trắng thành NaN, sau đó

df= df.dropna(subset=['col'])

4

Bạn có thể sử dụng biến thể này:

import pandas as pd
vals = {
    'name' : ['n1', 'n2', 'n3', 'n4', 'n5', 'n6', 'n7'],
    'gender' : ['m', 'f', 'f', 'f',  'f', 'c', 'c'],
    'age' : [39, 12, 27, 13, 36, 29, 10],
    'education' : ['ma', None, 'school', None, 'ba', None, None]
}
df_vals = pd.DataFrame(vals) #converting dict to dataframe

Điều này sẽ xuất ra (** - chỉ đánh dấu các hàng mong muốn):

   age education gender name
0   39        ma      m   n1 **
1   12      None      f   n2    
2   27    school      f   n3 **
3   13      None      f   n4
4   36        ba      f   n5 **
5   29      None      c   n6
6   10      None      c   n7

Vì vậy, để loại bỏ mọi thứ không có giá trị 'giáo dục', hãy sử dụng mã bên dưới:

df_vals = df_vals[~df_vals['education'].isnull()] 

('~' biểu thị KHÔNG)

Kết quả:

   age education gender name
0   39        ma      m   n1
2   27    school      f   n3
4   36        ba      f   n5
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.