2017-08-03 23 views
13

Tôi đang cố gắng cắt một khung dữ liệu dựa trên danh sách các giá trị, làm cách nào để tôi thực hiện việc này?Tập hợp con trả về dựa trên danh sách các giá trị boolean

Nói rằng tôi có một danh sách, l, và có vẻ như: [0,1,0,0,1,1,0,0,0,1]

Tôi muốn trả lại tất cả các hàng trong một dataframe, df, dựa trên nếu giá trị trong danh sách là một 1. Trong ví dụ này, Tôi sẽ bao gồm các hàng mà chỉ mục là 1, 4, 5 và 9. Bất kỳ cách dễ dàng nào để thực hiện việc này? Xin lỗi nếu đây là một câu hỏi dễ nhưng tôi vẫn quen với các khung dữ liệu.

+0

[Đây] (https://stackoverflow.com/help/someone-answers) là một cái gì đó để xem xét khi bạn đã nhận được câu trả lời có giá trị. – vestland

Trả lời

16

Bạn có thể sử dụng mặt nạ ở đây:

df[np.array([0,1,0,0,1,1,0,0,0,1],dtype=bool)] 

Vì vậy, chúng ta xây dựng một mảng boolean với true và false. Mỗi nơi mà mảng là True là một hàng chúng tôi chọn.

Hãy nhớ rằng chúng tôi làm không phải bộ lọc tại chỗ. Để lấy kết quả, bạn phải gán kết quả đến một (tùy chọn khác nhau) biến:

df2 = df[np.array([0,1,0,0,1,1,0,0,0,1],dtype=bool)] 
13

Chuyển đổi danh sách để một mảng boolean và sau đó sử dụng boolean lập chỉ mục:

df = pd.DataFrame(np.random.randint(10, size=(10, 3))) 

df[np.array(lst).astype(bool)] 
Out: 
    0 1 2 
1 8 6 3 
4 2 7 3 
5 7 2 3 
9 1 3 4 
11

Cài đặt
thiết lập Borrowed @ Ayhan của

df = pd.DataFrame(np.random.randint(10, size=(10, 3))) 

Without numpy
không phải là nhanh nhất, nhưng nó giữ riêng của mình và chắc chắn là ngắn nhất.

df[list(map(bool, lst))] 

    0 1 2 
1 3 5 6 
4 6 3 2 
5 5 7 6 
9 0 0 1 

Timing

results.div(results.min(1), 0).round(2).pipe(lambda d: d.assign(Best=d.idxmin(1))) 

     ayh wvo pir mxu wen Best 
N           
1  1.53 1.00 1.02 4.95 2.61 wvo 
3  1.06 1.00 1.04 5.46 2.84 wvo 
10  1.00 1.00 1.00 4.30 2.73 ayh 
30  1.00 1.05 1.24 4.06 3.76 ayh 
100  1.16 1.00 1.19 3.90 3.53 wvo 
300  1.29 1.00 1.32 2.50 2.38 wvo 
1000 1.54 1.00 2.19 2.24 3.85 wvo 
3000 1.39 1.00 2.17 1.81 4.55 wvo 
10000 1.22 1.00 2.21 1.35 4.36 wvo 
30000 1.19 1.00 2.26 1.39 5.36 wvo 
100000 1.19 1.00 2.19 1.31 4.82 wvo 

fig, (a1, a2) = plt.subplots(2, 1, figsize=(6, 6)) 
results.plot(loglog=True, lw=3, ax=a1) 
results.div(results.min(1), 0).round(2).plot.bar(logy=True, ax=a2) 
fig.tight_layout() 

enter image description here


Testing Mã

ayh = lambda d, l: d[np.array(l).astype(bool)] 
wvo = lambda d, l: d[np.array(l, dtype=bool)] 
pir = lambda d, l: d[list(map(bool, l))] 
wen = lambda d, l: d.loc[[i for i, x in enumerate(l) if x == 1], :] 

def mxu(d, l): 
    a = np.array(l) 
    return d.query('@a != 0') 

results = pd.DataFrame(
    index=pd.Index([1, 3, 10, 30, 100, 300, 
        1000, 3000, 10000, 30000, 100000], name='N'), 
    columns='ayh wvo pir mxu wen'.split(), 
    dtype=float 
) 

for i in results.index: 
    d = pd.concat([df] * i, ignore_index=True) 
    l = lst * i 
    for j in results.columns: 
     stmt = '{}(d, l)'.format(j) 
     setp = 'from __main__ import d, l, {}'.format(j) 
     results.set_value(i, j, timeit(stmt, setp, number=10)) 
+0

Bạn có thể vui lòng thử nghiệm 'df.loc [[i cho i, x trong liệt kê (lst) nếu x == 1] ,:]', nó phải là chậm nhất, nhưng chỉ tò mò nó sẽ chậm như thế nào ... – Wen

+0

@Wen tôi đã cập nhật – piRSquared

+0

Cảm ơn bạn ~ Tôi là điều tồi tệ nhất không nghi ngờ gì T_T – Wen

7

thêm một "sáng tạo" cách tiếp cận:

In [181]: a = np.array(lst) 

In [182]: df.query("index * @a > 0") 
Out[182]: 
    0 1 2 
1 1 5 5 
4 0 2 0 
5 4 9 9 
9 2 2 5 

hoặc much better variant from @ayhan:

In [183]: df.query("@a != 0") 
Out[183]: 
    0 1 2 
1 1 5 5 
4 0 2 0 
5 4 9 9 
9 2 2 5 

PS tôi cũng đã mượn @ setup Ayhan của

+1

Sẽ không phải 'df.query (" @ a> 0 ")' đủ? – ayhan

+1

@ayhan, vâng, thực sự, cảm ơn bạn! Điều đó trông sạch hơn nhiều. – MaxU

4

Hoặc có thể tìm thấy vị trí của 1 trong list và lát của bạn từ Dataframe

df.loc[[i for i,x in enumerate(lst) if x == 1],:] 
1

Lựa chọn sử dụng một danh sách các Booleans là một cái gì đó itertools.compress làm tốt.

Với

>>> df = pd.DataFrame(np.random.randint(10, size=(10, 2))) 
>>> selectors = [0, 1, 0, 0, 1, 1, 0, 0, 0, 1] 

>>> selected_idxs = list(itertools.compress(df.index, selectors)) # [1, 4, 5, 9] 
>>> df.iloc[selected_idxs, :] 
    0 1 
1 1 9 
4 3 4 
5 4 1 
9 8 9 
Các vấn đề liên quan