Hi all,
Is there a function that returns the inverse of ismissing()
?
Obviously, I can use ismissing(foo) == false
but it seems not elegant.
Thanks!
Hi all,
Is there a function that returns the inverse of ismissing()
?
Obviously, I can use ismissing(foo) == false
but it seems not elegant.
Thanks!
!ismissing
?
!ismissing()
Or, generally, for any function foo
that returns a boolean value, !foo
is a valid function that returns the inverse value.
it’s not because !ismissing()
is a separately defined function though, this is defined in Julia Base:
!(f::Function) = (x...)->!f(x...)
To be clear, if you do !ismissing(foo)
, this just calls ismissing(foo)
and then negates the result with !
If you use !ismissing
with no function call (...)
, then Julia uses the higher-order function @jling mentioned, which yields a function that is the antonym of ismissing
. This is useful for passing to other functions, e.g. for calling filter(!ismissing, somearray)
to extract the non-missing elements.
So the answer is that there is no inverse function to ismissing()
. But there are plenty of ways to generate the behaviour that such function would have.
anonymous functions are compiled too, so you lose no performance
this usually have a different meaning btw, an inverse function of f()
, let’s call it g()
, should have the property g(f(x)) == x
, which is impossible for ismissing
for obvious reason.
there’s nothing mystical about built-in functions, you can see the source code:
ismissing(x) = x === missing
you can define your:
isnotmissing(x) = x!== missing
if you really want…
Fwiw I would like for this to exist. The !
makes broadcasting ugly. .!ismissing.(x)
. But its purely aesthetic so it can live somewhere else.
@. !ismissing(x)
isn’t so bad, especially since you probably will have other function calls too. (I feel like @.
is under-used.)
It can’t be used in a function call without more parentheses is one issue.
Actually that might be a nice 2.0 breaking change, make
foo(@mymacro a, b)
have @mymacro
only apply to a
.
@. $foo(!ismissing(x), b)
should work, though I don’t know that it is better than foo(.!ismissing.(x), b)
. But I agree that macro calls inside function arguments are a bit annoying because of the parens.
I have defined the following function for my Jupyter notebooks:
broadwrap(f) = function (args...) broadcast(f, args...) end
But the name could be smaller or a single symbol. This function returns the broadcasted version of a function and I find it useful for some of the DataFrame
manipulation functions, which ask for a function working over a whole column as an argument.
This is what ByRow
does. It was written to do this exact operation, right?
In DataFramesMeta there is @rtransform
, @rselect
, @rsubset
, etc. for row-wise operations.
No, it seems like they have some distinctions:
But it may be the case that I created broadwrap
either by ignorance of ByRow
or before it existed; nonetheless, I am not sure if there is an advantage of using a more purpose-specific solution as I may end up using broadwrap
for one or another thing that does not relate to DataFrames.jl
(this is just its main use).
I would consider that a relatively niche difference. It’s also quite useful for data analysis, for example if you have a PooledArray and a function like f(x) = x + rand()
.
But you are right that ByRow
lives in DataFrames.jl. Maybe it should live somewhere else. But I’m not sure where.
Yes… but the goal of broadwrap
is to create a function
/closure
/callable
to be passed as an argument, there is a way to guarantee loop fusion when you are passing a function as argument?