2016-11-09 6 views
5

Ich möchte eine Reihe von Funktionen auf einen Wert anwenden und eine Reihe von Werten als Ausgabe erhalten. Ich sehe in help?> groupby (Datenrahmen-Paket) wir tun können:julia lang - Wie man mehrere Funktionen auf einen Wert anwendet

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

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

aber können wir tun

> [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 

oder sogar

> [sum, length](1:5) 

Ich würde den Ausgang erwarten:

[15, 5] 

Antwort

7

Ja und Nein. (das heißt ja, es ist möglich, aber nein, nicht mit dieser Syntax):


No: Die Syntax Sie mit |> und Datenrahmen sehen, ist nicht allgemeine Syntax. Es ist nur, wie die |> Methode für Datenrahmen definiert ist. Siehe seine Definition in der Datei grouping.jl (Zeile 377) und Sie werden sehen, dass es nur ein Wrapper für eine andere Funktion ist, und es ist definiert, entweder eine Funktion oder einen Vektor von Funktionen zu akzeptieren.

PS: Man beachte, dass die generischen |> die „pipes“ ein Argument in eine Funktion erwartet nur 1-Argumentfunktionen auf der rechten Seite, und hat sehr wenig mit dieser besonderen „Datenrahmen-überladenen“ Methode zu tun.


Ja: Sie können eine Reihe von Funktionen auf einen Satz von Eingaben auf andere Weise anzuwenden.
Ein einfacher Weg, z.B. wäre über eine Liste Verständnis:

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) 

Oder mit map:

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

usw.


PS: Wenn Sie daran interessiert sind |> zu verwenden, um dies zu erreichen, klar könnte man auch so etwas machen:

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

aber vermutlich, dass Niederlagen der Zweck von dem, was Sie zu tun versuchen :)

+1

Dank für den Hinweis, den Quellcode aus. Ich könnte das erweitern, um zu erreichen: "Import Base".(|>) (|>) {T <: Funktion} (a :: Array, fs :: Vektor {T}) = [f (a) für f in fs] > 1: 5 |> sammeln |> [Summe, Länge] 2-Element-Array {Int64,1}: '' ' – Phuoc

1

Ihre vorgeschlagene Syntax ist möglich in Julia durch ein Verfahren nach Art Zugabe Array{T} (hier T zu Subtypen beschränkt von Function): wenn die Anzahl der Funktionen

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 

dies ist jedoch eine große Overhead hat, ist gering. Für eine maximale Geschwindigkeit kann man Tuple s verwenden und eine @generated Funktion die Schleife manuell entrollen:

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

Das ist eine ausgezeichnete Antwort. Ich werde mehr über Julias Metaprogrammierung erfahren, http://docs.julaulang.org/en/release-0.5/manual/metaprogramming/ – Phuoc

Verwandte Themen