2016-11-09 56 views
5

Tôi muốn áp dụng một tập hợp các hàm cho một giá trị và nhận được một tập hợp các giá trị làm đầu ra. Tôi nhìn thấy trong help?> groupby (DataFrames gói), chúng tôi có thể làm:julia lang - cách áp dụng nhiều hàm cho một giá trị

> df |> groupby(:a) |> [sum, length] 

> df |> groupby([:a, :b]) |> [sum, length] 

nhưng chúng tôi có thể làm

> [sum, length](groupby([:a, :b])) 
MethodError: objects of type Array{Function,1} are not callable 
square brackets [] for indexing an Array. 
eval_user_input(::Any, ::Base.REPL.REPLBackend) at ./REPL.jl:64 
    in macro expansion at ./REPL.jl:95 [inlined] 
    in (::Base.REPL.##3#4{Base.REPL.REPLBackend})() at ./event.jl:68 

hoặc thậm chí

> [sum, length](1:5) 

Tôi mong chờ kết quả:

[15, 5] 

Trả lời

7

Có và không. (ví dụ: có nó là có thể, nhưng không, không phải với cú pháp đó):


Số: Cú pháp bạn nhìn thấy với |> và dataframes không phải là cú pháp chung. Nó chỉ là phương pháp |> được định nghĩa cho các khung dữ liệu. Xem định nghĩa của nó trong tập tin grouping.jl (dòng 377) và bạn sẽ thấy nó chỉ là một trình bao bọc cho một hàm khác, và nó được định nghĩa để chấp nhận một hàm hoặc một vectơ hàm.

PS: Lưu ý rằng |> chung chung là "đặt" một đối số vào hàm, chỉ mong đợi các hàm 1 đối số ở bên phải và có rất ít việc phải làm với phương pháp "dataframe-overloaded" cụ thể này.


Có: Bạn có thể áp dụng một tập hợp các chức năng để một tập hợp các nguyên liệu đầu vào theo những cách khác.
Một cách đơn giản, ví dụ: sẽ được thông qua một sự hiểu biết danh sách:

julia> a = [1 2 3;2 3 4]; 
julia> [f(a) for f in [sum, length, size]] 
3-element Array{Any,1}: 
15  
    6  
    (2,3) 

Hoặc sử dụng map:

julia> map((x) -> x(a), [sum, length, size]) 

, vv


PS: Nếu bạn muốn sử dụng |> để đạt được điều này, rõ ràng bạn cũng có thể làm điều gì đó như sau:

julia> a |> (x) -> [sum(x), length(x), size(x)] 

nhưng có lẽ đó đánh bại mục đích của những gì bạn đang cố gắng để làm :)

+1

Cảm ơn bạn đã chỉ ra mã nguồn. Tôi có thể mở rộng để đạt được: '' 'cơ sở nhập khẩu.(|>) (|>) {T <: Hàm} (a :: Mảng, fs :: Vector {T}) = [f (a) cho f trong fs] > 1: 5 |> thu thập |> [tổng, độ dài] Mảng 2 phần tử {Int64,1}: '' ' – Phuoc

1

cú pháp đề xuất của bạn là có thể trong Julia bằng cách thêm một phương pháp để loại Array{T} (ở đây, T bị hạn chế để phân nhóm của Function):

julia> (a::Array{T}){T<:Function}(x) = [f(x) for f in a] 

julia> [sin cos; exp sqrt](0) 
2×2 Array{Float64,2}: 
0.0 1.0 
1.0 0.0 

Tuy nhiên, điều này có chi phí lớn nếu số lượng chức năng nhỏ. Để có tốc độ tối đa, người ta có thể sử dụng Tuple s và chức năng @generated để hủy vòng lặp theo cách thủ công:

julia> @generated (t::NTuple{N, Function}){N}(x) = :($((:(t[$i](x)) for i in 1:N)...),) 

julia> (cos, sin)(0) 
(1.0,0.0) 
+0

Đó là câu trả lời tuyệt vời. Tôi sẽ tìm hiểu thêm về chương trình siêu lập trình của Julia, http://docs.julialang.org/en/release-0.5/manual/metaprogramming/ – Phuoc

Các vấn đề liên quan