Khi nào tôi muốn sử dụng pandas apply () trong mã của mình?


110

Tôi đã thấy nhiều câu trả lời được đăng cho các câu hỏi trên Stack Overflow liên quan đến việc sử dụng phương pháp Pandas apply. Tôi cũng đã thấy người dùng bình luận bên dưới họ nói rằng " applychậm và nên tránh".

Tôi đã đọc nhiều bài báo về chủ đề hiệu suất giải thích applylà chậm. Tôi cũng đã thấy tuyên bố từ chối trách nhiệm trong tài liệu về cách applyđơn giản là một hàm tiện lợi để chuyển UDF (dường như không thể tìm thấy điều đó bây giờ). Vì vậy, sự đồng thuận chung là applynên tránh nếu có thể. Tuy nhiên, điều này đặt ra những câu hỏi sau:

  1. Nếu applyquá tệ, thì tại sao nó lại nằm trong API?
  2. Làm thế nào và khi nào tôi nên đặt mã applymiễn phí?
  3. Có bao giờ bất kỳ tình huống mà applytốt (tốt hơn so với giải pháp khả thi khác)?

1
returns.add(1).apply(np.log)so với np.log(returns.add(1)là một trường hợp applythường sẽ nhanh hơn một chút, đó là hộp màu xanh lá cây phía dưới bên phải trong biểu đồ của jpp bên dưới.
Alexander

@Alexander cảm ơn. Không chỉ ra đầy đủ những tình huống này, nhưng chúng rất hữu ích để biết!
cs95

Câu trả lời:


107

apply, Chức năng Tiện lợi mà bạn không bao giờ Cần đến

Chúng tôi bắt đầu bằng cách giải quyết từng câu hỏi trong OP.

" Nếu áp dụng quá tệ, thì tại sao nó lại nằm trong API? "

DataFrame.applySeries.applycác hàm tiện lợi được định nghĩa trên DataFrame và đối tượng Series tương ứng. applychấp nhận bất kỳ chức năng nào do người dùng xác định áp dụng chuyển đổi / tổng hợp trên DataFrame. applythực sự là một viên đạn bạc mà bất kỳ chức năng nào hiện có của gấu trúc không thể làm được.

Một số điều applycó thể làm:

  • Chạy bất kỳ chức năng nào do người dùng xác định trên DataFrame hoặc Series
  • Áp dụng một hàm theo hàng ( axis=1) hoặc theo cột ( axis=0) trên DataFrame
  • Thực hiện căn chỉnh chỉ mục trong khi áp dụng chức năng
  • Thực hiện tổng hợp với các chức năng do người dùng xác định (tuy nhiên, chúng tôi thường thích agghoặc transformtrong những trường hợp này)
  • Thực hiện các phép biến đổi theo phần tử
  • Truyền kết quả tổng hợp đến các hàng gốc (xem result_typeđối số).
  • Chấp nhận các đối số vị trí / từ khóa để chuyển đến các hàm do người dùng xác định.

... Trong số những người khác. Để biết thêm thông tin, hãy xem Ứng dụng chức năng theo hàng hoặc theo cột trong tài liệu.

Vì vậy, với tất cả các tính năng, tại sao là applyxấu? Đó là bởi vì applynó là chậm . Pandas không đưa ra giả định nào về bản chất của chức năng của bạn và do đó, áp dụng lặp đi lặp lại chức năng của bạn cho từng hàng / cột nếu cần. Ngoài ra, việc xử lý tất cả các tình huống trên có nghĩa là applyphải chịu một số chi phí lớn ở mỗi lần lặp. Hơn nữa, applytiêu tốn nhiều bộ nhớ hơn, đây là một thách thức đối với các ứng dụng bị giới hạn bộ nhớ.

Có rất ít trường applyhợp thích hợp để sử dụng (thêm về điều đó bên dưới). Nếu bạn không chắc mình có nên sử dụng hay không apply, có lẽ bạn không nên.


Hãy giải quyết câu hỏi tiếp theo.

" Làm thế nào và khi nào tôi nên áp dụng miễn phí? "

Để diễn đạt lại, đây là một số tình huống phổ biến mà bạn sẽ muốn loại bỏ mọi cuộc gọi tới apply.

Dữ liệu số

Nếu bạn đang làm việc với dữ liệu số, có thể đã có một chức năng cython được vectơ hóa thực hiện chính xác những gì bạn đang cố gắng thực hiện (nếu không, vui lòng đặt câu hỏi trên Stack Overflow hoặc mở một yêu cầu tính năng trên GitHub).

Đối chiếu hiệu suất của applymột phép toán cộng đơn giản.

df = pd.DataFrame({"A": [9, 4, 2, 1], "B": [12, 7, 5, 4]})
df

   A   B
0  9  12
1  4   7
2  2   5
3  1   4

df.apply(np.sum)

A    16
B    28
dtype: int64

df.sum()

A    16
B    28
dtype: int64

Hiệu suất khôn ngoan, không có sự so sánh, tương đương với số hóa nhanh hơn nhiều. Không cần biểu đồ, vì sự khác biệt là rõ ràng ngay cả đối với dữ liệu đồ chơi.

%timeit df.apply(np.sum)
%timeit df.sum()
2.22 ms ± 41.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
471 µs ± 8.16 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Ngay cả khi bạn bật truyền mảng thô với rawđối số, nó vẫn chậm gấp đôi.

%timeit df.apply(np.sum, raw=True)
840 µs ± 691 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

Một vi dụ khac:

df.apply(lambda x: x.max() - x.min())

A    8
B    8
dtype: int64

df.max() - df.min()

A    8
B    8
dtype: int64

%timeit df.apply(lambda x: x.max() - x.min())
%timeit df.max() - df.min()

2.43 ms ± 450 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
1.23 ms ± 14.7 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Nói chung, hãy tìm các giải pháp thay thế được vector hóa nếu có thể.

Chuỗi / Regex

Pandas cung cấp các hàm chuỗi được "vectơ hóa" trong hầu hết các tình huống, nhưng có một số trường hợp hiếm hoi mà các hàm đó không ... "áp dụng", có thể nói như vậy.

Một vấn đề phổ biến là kiểm tra xem một giá trị trong một cột có xuất hiện trong một cột khác của cùng một hàng hay không.

df = pd.DataFrame({
    'Name': ['mickey', 'donald', 'minnie'],
    'Title': ['wonderland', "welcome to donald's castle", 'Minnie mouse clubhouse'],
    'Value': [20, 10, 86]})
df

     Name  Value                       Title
0  mickey     20                  wonderland
1  donald     10  welcome to donald's castle
2  minnie     86      Minnie mouse clubhouse

Điều này sẽ trả về hàng thứ hai và hàng thứ ba, vì "donald" và "minnie" có trong các cột "Tiêu đề" tương ứng của chúng.

Sử dụng ứng dụng, điều này sẽ được thực hiện bằng cách sử dụng

df.apply(lambda x: x['Name'].lower() in x['Title'].lower(), axis=1)

0    False
1     True
2     True
dtype: bool

df[df.apply(lambda x: x['Name'].lower() in x['Title'].lower(), axis=1)]

     Name                       Title  Value
1  donald  welcome to donald's castle     10
2  minnie      Minnie mouse clubhouse     86

Tuy nhiên, có một giải pháp tốt hơn bằng cách sử dụng khả năng hiểu danh sách.

df[[y.lower() in x.lower() for x, y in zip(df['Title'], df['Name'])]]

     Name                       Title  Value
1  donald  welcome to donald's castle     10
2  minnie      Minnie mouse clubhouse     86

%timeit df[df.apply(lambda x: x['Name'].lower() in x['Title'].lower(), axis=1)]
%timeit df[[y.lower() in x.lower() for x, y in zip(df['Title'], df['Name'])]]

2.85 ms ± 38.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
788 µs ± 16.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Điều cần lưu ý ở đây là các quy trình lặp đi lặp lại diễn ra nhanh hơn apply, vì chi phí thấp hơn. Nếu bạn cần xử lý NaN và các loại dtype không hợp lệ, bạn có thể xây dựng dựa trên điều này bằng cách sử dụng một hàm tùy chỉnh, sau đó bạn có thể gọi với các đối số bên trong khả năng hiểu danh sách.

Để biết thêm thông tin về thời điểm nên coi việc hiểu danh sách là một lựa chọn tốt, hãy xem bài viết của tôi: Đối với vòng lặp với gấu trúc - Khi nào tôi nên quan tâm? .

Lưu ý Các
hoạt động ngày và giờ cũng có các phiên bản được vector hóa. Vì vậy, ví dụ, bạn nên thích pd.to_datetime(df['date']), hơn, nói df['date'].apply(pd.to_datetime),.

Đọc thêm tại tài liệu .

Một cạm bẫy chung: Bùng nổ các cột danh sách

s = pd.Series([[1, 2]] * 3)
s

0    [1, 2]
1    [1, 2]
2    [1, 2]
dtype: object

Mọi người bị cám dỗ để sử dụng apply(pd.Series). Điều này thật kinh khủng về mặt hiệu suất.

s.apply(pd.Series)

   0  1
0  1  2
1  1  2
2  1  2

Một lựa chọn tốt hơn là làm phẳng cột và chuyển nó vào pd.DataFrame.

pd.DataFrame(s.tolist())

   0  1
0  1  2
1  1  2
2  1  2

%timeit s.apply(pd.Series)
%timeit pd.DataFrame(s.tolist())

2.65 ms ± 294 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
816 µs ± 40.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Cuối cùng,

" Có tình huống nào apply tốt không? "

Áp dụng là một chức năng tiện lợi, vì vậy có những tình huống mà chi phí không đáng kể đủ để tha thứ. Nó thực sự phụ thuộc vào số lần hàm được gọi.

Các hàm được Vectơ hóa cho Chuỗi chứ không phải DataFrames
Nếu bạn muốn áp dụng một thao tác chuỗi trên nhiều cột thì sao? Điều gì xảy ra nếu bạn muốn chuyển đổi nhiều cột thành datetime? Các hàm này chỉ được biểu diễn hóa cho Sê-ri, vì vậy chúng phải được áp dụng trên mỗi cột mà bạn muốn chuyển đổi / hoạt động.

df = pd.DataFrame(
         pd.date_range('2018-12-31','2019-01-31', freq='2D').date.astype(str).reshape(-1, 2), 
         columns=['date1', 'date2'])
df

       date1      date2
0 2018-12-31 2019-01-02
1 2019-01-04 2019-01-06
2 2019-01-08 2019-01-10
3 2019-01-12 2019-01-14
4 2019-01-16 2019-01-18
5 2019-01-20 2019-01-22
6 2019-01-24 2019-01-26
7 2019-01-28 2019-01-30

df.dtypes

date1    object
date2    object
dtype: object

Đây là một trường hợp được chấp nhận cho apply:

df.apply(pd.to_datetime, errors='coerce').dtypes

date1    datetime64[ns]
date2    datetime64[ns]
dtype: object

Lưu ý rằng nó cũng có ý nghĩa stackhoặc chỉ sử dụng một vòng lặp rõ ràng. Tất cả các tùy chọn này nhanh hơn một chút so với sử dụng apply, nhưng sự khác biệt đủ nhỏ để tha thứ.

%timeit df.apply(pd.to_datetime, errors='coerce')
%timeit pd.to_datetime(df.stack(), errors='coerce').unstack()
%timeit pd.concat([pd.to_datetime(df[c], errors='coerce') for c in df], axis=1)
%timeit for c in df.columns: df[c] = pd.to_datetime(df[c], errors='coerce')

5.49 ms ± 247 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
3.94 ms ± 48.1 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
3.16 ms ± 216 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
2.41 ms ± 1.71 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

Bạn có thể tạo một trường hợp tương tự cho các hoạt động khác như hoạt động chuỗi hoặc chuyển đổi thành danh mục.

u = df.apply(lambda x: x.str.contains(...))
v = df.apply(lambda x: x.astype(category))

v / s

u = pd.concat([df[c].str.contains(...) for c in df], axis=1)
v = df.copy()
for c in df:
    v[c] = df[c].astype(category)

Và như thế...

Chuyển đổi chuỗi thành str: astypeso vớiapply

Điều này có vẻ giống như một đặc điểm riêng của API. Việc sử dụng applyđể chuyển đổi số nguyên trong Chuỗi thành chuỗi có thể so sánh được (và đôi khi nhanh hơn) so với việc sử dụng astype.

nhập mô tả hình ảnh ở đây Biểu đồ được vẽ bằng cách sử dụng perfplotthư viện.

import perfplot

perfplot.show(
    setup=lambda n: pd.Series(np.random.randint(0, n, n)),
    kernels=[
        lambda s: s.astype(str),
        lambda s: s.apply(str)
    ],
    labels=['astype', 'apply'],
    n_range=[2**k for k in range(1, 20)],
    xlabel='N',
    logx=True,
    logy=True,
    equality_check=lambda x, y: (x == y).all())

Với phao, tôi thấy astypenó luôn nhanh bằng hoặc nhanh hơn một chút apply. Vì vậy, điều này liên quan đến thực tế là dữ liệu trong thử nghiệm là kiểu số nguyên.

GroupBy hoạt động với các phép biến đổi chuỗi

GroupBy.applyvẫn chưa được thảo luận cho đến bây giờ, nhưng GroupBy.applycũng là một hàm tiện lợi lặp đi lặp lại để xử lý bất cứ thứ gì mà các GroupByhàm hiện có không có.

Một yêu cầu phổ biến là thực hiện một GroupBy và sau đó là hai phép toán nguyên tố, chẳng hạn như "lagged cumsum":

df = pd.DataFrame({"A": list('aabcccddee'), "B": [12, 7, 5, 4, 5, 4, 3, 2, 1, 10]})
df

   A   B
0  a  12
1  a   7
2  b   5
3  c   4
4  c   5
5  c   4
6  d   3
7  d   2
8  e   1
9  e  10

Bạn sẽ cần hai cuộc gọi theo nhóm liên tiếp ở đây:

df.groupby('A').B.cumsum().groupby(df.A).shift()

0     NaN
1    12.0
2     NaN
3     NaN
4     4.0
5     9.0
6     NaN
7     3.0
8     NaN
9     1.0
Name: B, dtype: float64

Sử dụng apply, bạn có thể rút ngắn cuộc gọi này thành một cuộc gọi duy nhất.

df.groupby('A').B.apply(lambda x: x.cumsum().shift())

0     NaN
1    12.0
2     NaN
3     NaN
4     4.0
5     9.0
6     NaN
7     3.0
8     NaN
9     1.0
Name: B, dtype: float64

Rất khó để định lượng hiệu suất vì nó phụ thuộc vào dữ liệu. Nhưng nói chung, applylà một giải pháp có thể chấp nhận được nếu mục đích là giảm một groupbycuộc gọi (vì groupbycũng khá tốn kém).


Những lưu ý khác

Bên cạnh những lưu ý đã đề cập ở trên, cũng cần nhắc lại rằng applyhoạt động trên hàng (hoặc cột) đầu tiên hai lần. Điều này được thực hiện để xác định xem chức năng có bất kỳ tác dụng phụ nào không. Nếu không, applycó thể sử dụng đường dẫn nhanh để đánh giá kết quả, nếu không, nó sẽ rơi vào tình trạng triển khai chậm.

df = pd.DataFrame({
    'A': [1, 2],
    'B': ['x', 'y']
})

def func(x):
    print(x['A'])
    return x

df.apply(func, axis=1)

# 1
# 1
# 2
   A  B
0  1  x
1  2  y

Hành vi này cũng được thấy GroupBy.applytrên các phiên bản gấu trúc <0,25 (nó đã được sửa cho 0,25, xem tại đây để biết thêm thông tin .)


Tôi nghĩ chúng ta cần phải cẩn thận .. %timeit for c in df.columns: df[c] = pd.to_datetime(df[c], errors='coerce')chắc chắn sau lần lặp đầu tiên, nó sẽ nhanh hơn nhiều vì bạn đang chuyển đổi datetimethành ... datetime?
jpp

@jpp Tôi có cùng mối quan tâm. Nhưng bạn vẫn cần thực hiện quét tuyến tính theo một trong hai cách, gọi to_datetime trên chuỗi cũng nhanh như gọi chúng trên các đối tượng datetime, nếu không muốn nói là nhanh hơn. Thời gian của sân bóng giống nhau. Giải pháp thay thế sẽ là thực hiện một số bước sao chép trước cho mọi giải pháp định thời gian làm xa điểm chính. Nhưng đó là một mối quan tâm hợp lệ.
cs95

"Gọi to_datetimetrên dây nhanh như trên ... datetimeđồ vật" .. thật không? Tôi đã bao gồm việc tạo khung dữ liệu (chi phí cố định) trong thời gian applyso với forvòng lặp và sự khác biệt nhỏ hơn nhiều.
jpp

@jpp Chà, đó là những gì tôi nhận được từ thử nghiệm (thừa nhận là có giới hạn) của mình. Tôi chắc chắn rằng nó phụ thuộc vào dữ liệu, nhưng ý tưởng chung là với mục đích minh họa, sự khác biệt là "nghiêm túc, đừng lo lắng về nó".
cs95

1
@ cs95, Chúc mừng năm mới!
jpp

48

Không phải tất cả applyđều giống nhau

Biểu đồ dưới đây gợi ý khi nào nên xem xét apply1 . Màu xanh lá cây có nghĩa là có thể hiệu quả; đỏ tránh.

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

Một số điều này là trực quan: pd.Series.applylà một vòng lặp hàng-khôn-ngoan cấp Python, ditto pd.DataFrame.applyhàng-khôn ngoan ( axis=1). Việc lạm dụng chúng rất nhiều và trên phạm vi rộng. Bài viết khác đề cập đến chúng chuyên sâu hơn. Các giải pháp phổ biến là sử dụng các phương pháp vectorised, danh sách hiểu rõ (giả định dữ liệu sạch) hoặc các công cụ hiệu quả như hàm pd.DataFrametạo (ví dụ: tránh apply(pd.Series)).

Nếu bạn đang sử dụng theo pd.DataFrame.applyhàng, việc chỉ định raw=True(nếu có thể) thường có lợi. Ở giai đoạn này, numbathường là một lựa chọn tốt hơn.

GroupBy.apply: thường được ưa chuộng

Các groupbythao tác lặp đi lặp lại để tránh applysẽ ảnh hưởng đến hiệu suất. GroupBy.applyở đây thường ổn, miễn là các phương pháp bạn sử dụng trong chức năng tùy chỉnh của mình đã được vector hóa. Đôi khi không có phương pháp Pandas bản địa nào cho tập hợp theo nhóm mà bạn muốn áp dụng. Trong trường hợp này, đối với một số nhóm nhỏ applycó chức năng tùy chỉnh vẫn có thể cung cấp hiệu suất hợp lý.

pd.DataFrame.apply cột khôn ngoan: một túi hỗn hợp

pd.DataFrame.applycột-khôn ( axis=0) là một trường hợp thú vị. Đối với một số lượng nhỏ các hàng so với một số lượng lớn các cột, nó hầu như luôn luôn đắt tiền. Đối với một số lượng lớn hàng liên quan đến cột, trường hợp phổ biến hơn, đôi khi bạn có thể thấy các cải thiện hiệu suất đáng kể bằng cách sử dụng apply:

# Python 3.7, Pandas 0.23.4
np.random.seed(0)
df = pd.DataFrame(np.random.random((10**7, 3)))     # Scenario_1, many rows
df = pd.DataFrame(np.random.random((10**4, 10**3))) # Scenario_2, many columns

                                               # Scenario_1  | Scenario_2
%timeit df.sum()                               # 800 ms      | 109 ms
%timeit df.apply(pd.Series.sum)                # 568 ms      | 325 ms

%timeit df.max() - df.min()                    # 1.63 s      | 314 ms
%timeit df.apply(lambda x: x.max() - x.min())  # 838 ms      | 473 ms

%timeit df.mean()                              # 108 ms      | 94.4 ms
%timeit df.apply(pd.Series.mean)               # 276 ms      | 233 ms

1 Có những trường hợp ngoại lệ, nhưng những trường hợp này thường là bên lề hoặc không phổ biến. Một vài ví dụ:

  1. df['col'].apply(str)có thể tốt hơn một chút df['col'].astype(str).
  2. df.apply(pd.to_datetime)làm việc trên chuỗi không mở rộng quy mô tốt với các hàng so với một forvòng lặp thông thường .

2
Cảm ơn bạn đã tham gia, đánh giá cao nhiều quan điểm :) +1
cs95

1
@coldspeed, Cảm ơn, không có gì sai với bài đăng của bạn (ngoại trừ một số điểm chuẩn mâu thuẫn so với của tôi, nhưng có thể là đầu vào hoặc dựa trên thiết lập). Chỉ cảm thấy có một cách khác để nhìn nhận vấn đề.
jpp

@jpp tôi luôn luôn sử dụng bạn sơ đồ xuất sắc đang là hướng dẫn cho đến khi tôi nhìn thấy ngày hôm nay rằng một hàng khôn ngoanapply là đáng kể nhanh hơn so với giải pháp của tôi với any. Bất kỳ suy nghĩ về điều này?
Stef

1
@jpp: bạn nói đúng: đối với hàng 1mio x 100 cols anynhanh hơn khoảng 100 lần apply. Nó đã thực hiện các thử nghiệm đầu tiên của tôi với 2000 hàng x 1000 cols và ở đây applynhanh gấp đôiany
Stef

1
@jpp Tôi muốn sử dụng hình ảnh của bạn trong một bài thuyết trình / bài báo. Bạn có ý với điều đó? Tôi rõ ràng sẽ đề cập đến nguồn. Cảm ơn
Erfan

3

Đối với axis=1(tức là các hàm khôn ngoan theo hàng) thì bạn chỉ có thể sử dụng hàm sau thay cho apply. Tôi tự hỏi tại sao đây không phải là pandashành vi. (Chưa được thử nghiệm với các chỉ mục phức hợp, nhưng nó có vẻ nhanh hơn nhiều apply)

def faster_df_apply(df, func):
    cols = list(df.columns)
    data, index = [], []
    for row in df.itertuples(index=True):
        row_dict = {f:v for f,v in zip(cols, row[1:])}
        data.append(func(row_dict))
        index.append(row[0])
    return pd.Series(data, index=index)

Tôi rất ngạc nhiên khi thấy điều này đã mang lại cho tôi hiệu suất tốt hơn trong một số trường hợp. Nó đặc biệt hữu ích khi tôi cần làm nhiều việc, mỗi thứ có một tập hợp con giá trị cột khác nhau. Câu trả lời "Tất cả các ứng dụng không giống nhau" có thể giúp tìm ra khi nào nó có khả năng hữu ích nhưng không quá khó để kiểm tra trên một mẫu dữ liệu của bạn.
denson

Một vài gợi ý: đối với hiệu suất, khả năng hiểu danh sách sẽ tốt hơn vòng lặp for; zip(df, row[1:])ở đây là đủ; thực sự, ở giai đoạn này, hãy xem xét numbanếu func là một phép tính số. Xem câu trả lời này để được giải thích.
jpp

@jpp - nếu bạn có chức năng tốt hơn hãy chia sẻ. Tôi nghĩ rằng điều này là khá gần với tối ưu từ phân tích của tôi. Yes numbalà nhanh hơn, faster_df_applydành cho những người chỉ muốn một cái gì đó tương đương, nhưng nhanh hơn, DataFrame.apply(chậm một cách kỳ lạ).
Pete Cacioppi

2

Có bao giờ bất kỳ tình huống nào applytốt không? Vâng, thỉnh thoảng.

Nhiệm vụ: giải mã chuỗi Unicode.

import numpy as np
import pandas as pd
import unidecode

s = pd.Series(['mañana','Ceñía'])
s.head()
0    mañana
1     Ceñía


s.apply(unidecode.unidecode)
0    manana
1     Cenia

Cập nhật
Tôi không ủng hộ việc sử dụng apply, chỉ nghĩ vì NumPykhông thể đối phó với tình huống trên, nó có thể là một ứng cử viên tốt cho pandas apply. Nhưng tôi đã quên phần hiểu danh sách đơn giản nhờ lời nhắc của @jpp.


Ồ không. Làm thế nào là điều này tốt hơn [unidecode.unidecode(x) for x in s]hoặc list(map(unidecode.unidecode, s))?
jpp

1
Vì nó đã là một loạt phim về gấu trúc, tôi đã bị cám dỗ để sử dụng apply, Yeah bạn đúng, sử dụng list-comp tốt hơn là apply, Nhưng downvote hơi khắc nghiệt, tôi không ủng hộ apply, chỉ nghĩ rằng điều này có thể là tốt ca sử dụng.
astro123 27/02/19
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.