python pandas: áp dụng một hàm với các đối số cho một chuỗi


147

Tôi muốn áp dụng một hàm với các đối số cho một chuỗi trong gấu trúc python:

x = my_series.apply(my_function, more_arguments_1)
y = my_series.apply(my_function, more_arguments_2)
...

Các tài liệu mô tả sự hỗ trợ cho một phương pháp áp dụng, nhưng nó không chấp nhận bất kỳ đối số. Có một phương pháp khác chấp nhận đối số? Ngoài ra, tôi có thiếu một cách giải quyết đơn giản?

Cập nhật (tháng 10 năm 2017): Lưu ý rằng vì câu hỏi này ban đầu được hỏi rằng gấu trúc apply()đã được cập nhật để xử lý các đối số từ khóa và vị trí và liên kết tài liệu ở trên phản ánh điều đó và cho biết cách bao gồm một trong hai loại đối số.


3
Tại sao không chỉ sử dụng functools.partial, hoặc starmap?
Joel Cornett

Câu trả lời:


170

Phiên bản mới của gấu trúc làm cho phép bạn vượt qua đối số phụ (xem tài liệu mới ). Vì vậy, bây giờ bạn có thể làm:

my_series.apply(your_function, args=(2,3,4), extra_kw=1)

Các đối số vị trí được thêm vào sau phần tử của chuỗi.


Đối với phiên bản cũ của gấu trúc:

Các tài liệu giải thích điều này rõ ràng. Phương thức áp dụng chấp nhận hàm python cần có một tham số. Nếu bạn muốn truyền nhiều tham số hơn, bạn nên sử dụng functools.partialtheo đề xuất của Joel Cornett trong bình luận của mình.

Một ví dụ:

>>> import functools
>>> import operator
>>> add_3 = functools.partial(operator.add,3)
>>> add_3(2)
5
>>> add_3(7)
10

Bạn cũng có thể vượt qua các đối số từ khóa bằng cách sử dụng partial.

Một cách khác là tạo ra lambda:

my_series.apply((lambda x: your_func(a,b,c,d,...,x)))

Nhưng tôi nghĩ sử dụng partiallà tốt hơn.


12
Đối với một DataFrame, phương thức áp dụng chấp nhận argsđối số, đó là một tuple giữ các đối số vị trí bổ sung hoặc ** kwds cho các đối số được đặt tên. Tôi đã tạo một vấn đề để có điều này cũng cho Series.apply () github.com/pydata/pandas/issues/1829
Wouter Overmeire

28
Tính năng đã được triển khai, sẽ có trong phiên bản phát hành gấu trúc sắp tới
Wes McKinney

4
Đây là một câu trả lời hay nhưng 2/3 đầu tiên của nó thực sự lỗi thời. IMO, câu trả lời này có thể được cập nhật độc đáo bằng cách chỉ là một liên kết đến tài liệu mới cộng với một ví dụ ngắn gọn về cách sử dụng với vị trí và / hoặc từ khóa args. Chỉ cần FWIW và không chỉ trích câu trả lời ban đầu, sẽ chỉ được hưởng lợi từ một bản cập nhật IMO, đặc biệt vì đây là câu trả lời thường xuyên được đọc.
JohnE

@watsonic Tài liệu đã được cập nhật và nhấp vào các liên kết cũ dẫn đến tài liệu hiện tại hiện đang trả lời câu hỏi rất hay.
JohnE

Lưu ý: Nếu bạn đang truyền một đối số chuỗi đơn, chẳng hạn 'abc', thì args=('abc')sẽ được đánh giá là ba đối số ('a', 'b', 'c'). Để tránh điều này, bạn phải vượt qua một tuple chứa chuỗi và để thực hiện điều đó, bao gồm dấu phẩy:args=('abc',)
Rocky K

82

Các bước:

  1. Tạo một khung dữ liệu
  2. Tạo một chức năng
  3. Sử dụng các đối số được đặt tên của hàm trong câu lệnh áp dụng.

Thí dụ

x=pd.DataFrame([1,2,3,4])  

def add(i1, i2):  
    return i1+i2

x.apply(add,i2=9)

Kết quả của ví dụ này là mỗi số trong khung dữ liệu sẽ được thêm vào số 9.

    0
0  10
1  11
2  12
3  13

Giải trình:

Hàm "add" có hai tham số: i1, i2. Tham số đầu tiên sẽ là giá trị trong khung dữ liệu và thứ hai là bất cứ thứ gì chúng ta chuyển đến hàm "áp dụng". Trong trường hợp này, chúng tôi chuyển "9" cho hàm áp dụng bằng cách sử dụng đối số từ khóa "i2".


2
Chính xác những gì tôi đang tìm kiếm. Đáng chú ý, điều này không yêu cầu tạo một chức năng tùy chỉnh chỉ để xử lý Sê-ri (hoặc df). Hoàn hảo!
Connor

Câu hỏi duy nhất còn lại là: Làm thế nào để chuyển một đối số từ khóa cho đối số đầu tiên trong add (i1) và lặp lại với i2?
Connor

Tôi nghĩ rằng đây là câu trả lời tốt nhất
crypdick

43
Series.apply(func, convert_dtype=True, args=(), **kwds)

args : tuple

x = my_series.apply(my_function, args = (arg1,))

11
Cảm ơn! Bạn có thể giải thích tại sao args = (arg1,) cần một dấu phẩy sau đối số đầu tiên không?
DrMisha

21
@MishaTeplitskiy, bạn cần có dấu phẩy để Python hiểu nội dung của dấu ngoặc đơn là một tuple có độ dài 1.
prooffreader

3
Những gì về đưa vào args cho func. Vì vậy, nếu tôi muốn áp dụng pd.Series.mean(axis=1)làm thế nào để tôi đưa vào axis=1?
Bàn Bobby nhỏ

1
Là một mặt lưu ý, bạn cũng có thể thêm một đối số từ khóa mà không cần sử dụng thẻ <args> tham số (ví dụ: x = my_series.apply (my_function, keyword_arg = arg1), trong đó <keyword_arg> là một trong những thông số đầu vào của my_function)
lev

1
phản hồi này quá ngắn và không giải thích được gì
FistOfFury

23

Bạn có thể chuyển bất kỳ số lượng đối số nào cho hàm applyđang gọi thông qua các đối số chưa được đặt tên, được chuyển dưới dạng một tuple cho argstham số hoặc thông qua các đối số từ khóa khác được ghi trong từ điển theo kwdstham số.

Chẳng hạn, hãy xây dựng một hàm trả về True cho các giá trị trong khoảng từ 3 đến 6 và ngược lại là Sai.

s = pd.Series(np.random.randint(0,10, 10))
s

0    5
1    3
2    1
3    1
4    6
5    0
6    3
7    4
8    9
9    6
dtype: int64

s.apply(lambda x: x >= 3 and x <= 6)

0     True
1     True
2    False
3    False
4     True
5    False
6     True
7     True
8    False
9     True
dtype: bool

Chức năng ẩn danh này không linh hoạt. Hãy tạo một hàm bình thường với hai đối số để kiểm soát các giá trị tối thiểu và tối đa mà chúng ta muốn trong Sê-ri của chúng tôi.

def between(x, low, high):
    return x >= low and x =< high

Chúng ta có thể sao chép đầu ra của hàm đầu tiên bằng cách chuyển các đối số không tên cho args:

s.apply(between, args=(3,6))

Hoặc chúng ta có thể sử dụng các đối số được đặt tên

s.apply(between, low=3, high=6)

Hoặc thậm chí là sự kết hợp của cả hai

s.apply(between, args=(3,), high=6)
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.