Cột thùng rác có gấu trúc trăn


99

Tôi có cột Khung dữ liệu với các giá trị số:

df['percentage'].head()
46.5
44.2
100.0
42.12

Tôi muốn xem cột là số lượng bin:

bins = [0, 1, 5, 10, 25, 50, 100]

Làm thế nào tôi có thể nhận được kết quả là thùng với của họ value counts?

[0, 1] bin amount
[1, 5] etc 
[5, 10] etc 
......

Câu trả lời:


186

Bạn có thể sử dụng pandas.cut:

bins = [0, 1, 5, 10, 25, 50, 100]
df['binned'] = pd.cut(df['percentage'], bins)
print (df)
   percentage     binned
0       46.50   (25, 50]
1       44.20   (25, 50]
2      100.00  (50, 100]
3       42.12   (25, 50]

bins = [0, 1, 5, 10, 25, 50, 100]
labels = [1,2,3,4,5,6]
df['binned'] = pd.cut(df['percentage'], bins=bins, labels=labels)
print (df)
   percentage binned
0       46.50      5
1       44.20      5
2      100.00      6
3       42.12      5

Hoặc numpy.searchsorted:

bins = [0, 1, 5, 10, 25, 50, 100]
df['binned'] = np.searchsorted(bins, df['percentage'].values)
print (df)
   percentage  binned
0       46.50       5
1       44.20       5
2      100.00       6
3       42.12       5

... và sau đó value_countshoặc groupbyvà tổng hợp size:

s = pd.cut(df['percentage'], bins=bins).value_counts()
print (s)
(25, 50]     3
(50, 100]    1
(10, 25]     0
(5, 10]      0
(1, 5]       0
(0, 1]       0
Name: percentage, dtype: int64

s = df.groupby(pd.cut(df['percentage'], bins=bins)).size()
print (s)
percentage
(0, 1]       0
(1, 5]       0
(5, 10]      0
(10, 25]     0
(25, 50]     3
(50, 100]    1
dtype: int64

Theo mặc định cuttrở lại categorical.

Seriescác phương thức như Series.value_counts()sẽ sử dụng tất cả các danh mục, ngay cả khi một số danh mục không có trong dữ liệu, các phép toán trong phân loại .


mà không bins = [0, 1, 5, 10, 25, 50, 100], tôi có thể chỉ nói tạo 5 thùng và nó sẽ cắt nó theo mức cắt trung bình? ví dụ: tôi có 110 bản ghi, tôi muốn cắt chúng thành 5 thùng với 22 bản ghi trong mỗi thùng.
qqqwww

2
@qqqwww - Không chắc nếu hiểu, bạn có nghĩ qcutvậy không? liên kết
jezrael

@qqqwww để làm điều đó, ví dụ pd.cut trong trang của nó cho thấy nó: pd.cut (np.array ([1, 7, 5, 4, 6, 3]), 3) sẽ cắt mảng thành 3 phần bằng nhau.
Ayan Mitra

@jezreal bạn có thể gợi ý cách tính giá trị trung bình của từng thùng được không?
Ayan Mitra

1
@AyanMitra - Bạn có nghĩ df.groupby(pd.cut(df['percentage'], bins=bins)).mean()vậy không?
jezrael

4

Sử dụng numbamô-đun để tăng tốc.

Trên bộ dữ liệu lớn ( 500k >) pd.cutcó thể khá chậm cho việc phân loại dữ liệu.

Tôi đã viết hàm của riêng mình numbabằng cách biên dịch đúng lúc, tức là 16xnhanh hơn:

from numba import njit

@njit
def cut(arr):
    bins = np.empty(arr.shape[0])
    for idx, x in enumerate(arr):
        if (x >= 0) & (x < 1):
            bins[idx] = 1
        elif (x >= 1) & (x < 5):
            bins[idx] = 2
        elif (x >= 5) & (x < 10):
            bins[idx] = 3
        elif (x >= 10) & (x < 25):
            bins[idx] = 4
        elif (x >= 25) & (x < 50):
            bins[idx] = 5
        elif (x >= 50) & (x < 100):
            bins[idx] = 6
        else:
            bins[idx] = 7

    return bins
cut(df['percentage'].to_numpy())

# array([5., 5., 7., 5.])

Tùy chọn: bạn cũng có thể ánh xạ nó vào thùng dưới dạng chuỗi:

a = cut(df['percentage'].to_numpy())

conversion_dict = {1: 'bin1',
                   2: 'bin2',
                   3: 'bin3',
                   4: 'bin4',
                   5: 'bin5',
                   6: 'bin6',
                   7: 'bin7'}

bins = list(map(conversion_dict.get, a))

# ['bin5', 'bin5', 'bin7', 'bin5']

So sánh tốc độ :

# create dataframe of 8 million rows for testing
dfbig = pd.concat([df]*2000000, ignore_index=True)

dfbig.shape

# (8000000, 1)
%%timeit
cut(dfbig['percentage'].to_numpy())

# 38 ms ± 616 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
%%timeit
bins = [0, 1, 5, 10, 25, 50, 100]
labels = [1,2,3,4,5,6]
pd.cut(dfbig['percentage'], bins=bins, labels=labels)

# 215 ms ± 9.76 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
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.