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…
(Yes, I would call what @drarnau wants the “antonym” of ismissing
.)
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.
The practical problem with this is that, unlike dot calls, it won’t fuse.
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?