2016-11-09 13 views
5

Chciałbym zastosować zestaw funkcji do wartości i uzyskać zestaw wartości jako wynik. Widzę w help?> groupby (pakiet DataFrames) możemy zrobić:julia lang - jak zastosować wiele funkcji do wartości

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

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

ale możemy zrobić

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

lub nawet

> [sum, length](1:5) 

spodziewałbym wyjście:

[15, 5] 

Odpowiedz

7

Tak i nie. (to tak, że to możliwe, ale nie, nie z tej składni):


nr: Składnia widać z |> i dataframes nie jest składnia ogóle. Tak właśnie zdefiniowano metodę |> dla ramek danych. Zobacz jego definicję w pliku grouping.jl (wiersz 377), a zobaczysz, że jest to tylko otok do innej funkcji i zdefiniowano, że akceptuje funkcję lub wektor funkcji.

PS: Należy pamiętać, że generyczny |> który „rury” argument do funkcji, oczekuje tylko funkcje 1-argumentu po prawej stronie i ma bardzo niewiele wspólnego z tym konkretnym „dataframe-przeciążony” metody.


Tak: Można zastosować zestaw funkcji do zestawu wejść w inny sposób.
Jeden prosty sposób, np. będzie poprzez listowego:

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) 

lub używając map:

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

itp


PS: Jeśli jesteś chętni do korzystania |> do osiągnięcia tego celu, oczywiście możesz również zrobić coś takiego:

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

ale przypuszczalnie że celowość tego, co starasz się zrobić :)

+1

Dzięki za wskazanie kodu źródłowego. Mogę to rozszerzyć, aby osiągnąć: '' 'import Base.(|>) (|>) {T <: Funkcja} (a :: Array, fs :: Wektor {T}) = [f (a) dla f in fs) > 1: 5 |> zbie | |> [suma, długość] Tablica 2-elementowa {Int64,1}: '' ' – Phuoc

1

składni proponowane jest możliwe Julia dodając metodę typu Array{T} (tu T jest ograniczony do podtypów z 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 

to jednak ma duży narzut jeśli liczba funkcji jest niewielka. W celu uzyskania maksymalnej szybkości, można stosować Tuple S i @generated celu odwinięcia pętlę ręcznie:

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

To doskonała odpowiedź. Dowiesz się więcej o metaprogramowaniu Julii, http://docs.julialang.org/en/release-0.5/manual/metaprogramming/ – Phuoc

Powiązane problemy