Hướng dẫn dùng pandas factorize python

Bạn có thể sử dụng applynếu bạn cần factorizetừng cột riêng biệt:

df = pd.DataFrame({'A':['type1','type2','type2'],
                   'B':['type1','type2','type3'],
                   'C':['type1','type3','type3']})

print (df)
       A      B      C
0  type1  type1  type1
1  type2  type2  type3
2  type2  type3  type3

print (df.apply(lambda x: pd.factorize(x)[0]))
   A  B  C
0  0  0  0
1  1  1  1
2  1  2  1

Nếu bạn cần cùng một giá trị chuỗi, cùng một giá trị số:

print (df.stack().rank(method='dense').unstack())
     A    B    C
0  1.0  1.0  1.0
1  2.0  2.0  3.0
2  2.0  3.0  3.0

Nếu bạn chỉ cần áp dụng hàm cho một số cột, hãy sử dụng một tập hợp con:

df[['B','C']] = df[['B','C']].stack().rank(method='dense').unstack()
print (df)
       A    B    C
0  type1  1.0  1.0
1  type2  2.0  3.0
2  type2  3.0  3.0

Giải pháp với factorize:

stacked = df[['B','C']].stack()
df[['B','C']] = pd.Series(stacked.factorize()[0], index=stacked.index).unstack()
print (df)
       A  B  C
0  type1  0  0
1  type2  1  2
2  type2  2  2

Bạn có thể dịch lại chúng mapbằng cách dict, trong đó bạn cần loại bỏ các bản sao bằng cách drop_duplicates:

vals = df.stack().drop_duplicates().values
b = [x for x in df.stack().drop_duplicates().rank(method='dense')]

d1 = dict(zip(b, vals))
print (d1)
{1.0: 'type1', 2.0: 'type2', 3.0: 'type3'}

df1 = df.stack().rank(method='dense').unstack()
print (df1)
     A    B    C
0  1.0  1.0  1.0
1  2.0  2.0  3.0
2  2.0  3.0  3.0

print (df1.stack().map(d1).unstack())
       A      B      C
0  type1  type1  type1
1  type2  type2  type3
2  type2  type3  type3

40 hữu ích 5 bình luận chia sẻ

Hãy bắt đầu với một mảng dữ liệu ngẫu nhiên (có thể tái tạo) -

# Setup
In [11]: np.random.seed(0)
    ...: a = np.random.randint(0,9,(7,2))
    ...: a[2] = a[0]
    ...: a[4] = a[1]
    ...: a[6] = a[1]

# Check values
In [12]: a
Out[12]: 
array([[5, 0],
       [3, 3],
       [5, 0],
       [5, 2],
       [3, 3],
       [6, 8],
       [3, 3]])

# Check its itemsize
In [13]: a.dtype.itemsize
Out[13]: 8

Hãy xem mỗi hàng như một đại lượng vô hướng bằng cách sử dụng kiểu dữ liệu tùy chỉnh bao gồm hai phần tử. Chúng tôi sẽ sử dụng void-dtypecho mục đích này. Như đã đề cập trong tài liệu -

https://docs.scipy.org/doc/numpy-1.13.0/reference/arrays.dtypes.html#specification-and-construct-data-types , https://docs.scipy.org/doc/numpy- 1.13.0 / reference / mảng.interface.html # mảng-giao diện ) và trong Câu hỏi và Đáp của stackoverflow , có vẻ như điều đó sẽ là:

In [23]: np.dtype((np.void, 16)) # 8 is the itemsize, so 8x2=16
Out[23]: dtype('V16')

# Create new view of the input
In [14]: b = a.view('V16').ravel()

# Check new view array
In [15]: b
Out[15]: 
array([b'\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
       b'\x03\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00',
       b'\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
       b'\x05\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00',
       b'\x03\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00',
       b'\x06\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00',
       b'\x03\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00'],
      dtype='|V16')

# Use pandas.factorize on the new view
In [16]: pd.factorize(b)
Out[16]: 
(array([0, 1, 0, 0, 1, 2, 1]),
 array(['\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
        '\x03\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00',
        '\x06\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00'],
       dtype=object))

Hai điều ngoài yếu tố đầu ra mà tôi không thể hiểu được và do đó, các câu hỏi tiếp theo -

  1. Phần tử thứ tư của đầu ra đầu tiên (= 0) có vẻ sai, vì nó có cùng ID với phần tử thứ ba, nhưng trong đó b, phần tử thứ tư và thứ ba khác nhau. Tại sao như vậy?

  2. Tại sao đầu ra thứ hai có loại đối tượng, trong khi loại bV16. Điều này cũng gây ra giá trị sai được đề cập trong 1.?

Một câu hỏi lớn hơn có thể là - Có pandas.factorizebao gồm các kiểu dữ liệu tùy chỉnh không? Từ tài liệu, tôi thấy:

giá trị: dãy A 1-D dãy. Các chuỗi không phải là đối tượng gấu trúc được ép buộc vào ndarrays trước khi phân tích nhân tử.

Trong trường hợp mẫu được cung cấp, chúng tôi có một mảng NumPy, vì vậy người ta sẽ giả định không có vấn đề gì với đầu vào, trừ khi tài liệu không làm rõ về phần kiểu dữ liệu tùy chỉnh?

Thiết lập hệ thống: Ubuntu 16.04, Python: 2.7.12, NumPy: 1.16.2, Pandas: 0.24.2.

Trên Python-3.x

Thiết lập hệ thống: Ubuntu 16.04, Python: 3.5.2, NumPy: 1.16.2, Pandas: 0.24.2.

Chạy cùng một thiết lập, tôi nhận được -

In [18]: b
Out[18]: 
array([b'\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
       b'\x03\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00',
       b'\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
       b'\x05\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00',
       b'\x03\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00',
       b'\x06\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00',
       b'\x03\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00'],
      dtype='|V16')

In [19]: pd.factorize(b)
Out[19]: 
(array([0, 1, 0, 2, 1, 3, 1]),
 array([b'\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00',
        b'\x03\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00',
        b'\x05\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00',
        b'\x06\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00'],
       dtype=object))

Vì vậy, kết quả đầu tiên tắt có factorizevẻ ổn ở đây. Nhưng, đầu ra thứ hai lại có kiểu đối tượng, khác với đầu vào. Vì vậy, cùng một câu hỏi - Tại sao loại dtype này lại thay đổi?

Biên dịch các câu hỏi / tl; dr

Với kiểu dữ liệu tùy chỉnh như vậy:

  1. Tại sao sai labels, uniquesvà khác nhau uniquesdtype trên Python2.x?

  2. Tại sao loại uniquesdtype khác nhau trên Python3.x?

9 hữu ích 0 bình luận 830 xem chia sẻ