Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ARROW-10640: [C++] An "if_else" kernel to combine two arrays based on a mask #10410

Closed
wants to merge 39 commits into from

Conversation

nirandaperera
Copy link
Contributor

Adding a preliminary impl for an if_else(cond: Datum, left: Datum, right: Datum) function. It works as follows,

def if_else(cond, left, right):
    for c, true_val, false_val in zip(cond, left, right):
        if c:
            yield true_val
        else:
            yield false_val

null values will be promoted to the output.

@github-actions
Copy link

@pitrou pitrou self-requested a review May 26, 2021 18:28
@nirandaperera
Copy link
Contributor Author

@bkietz I think the bitmap ops approach is simpler than the bitmap visitor approach. WDYT?
bitmap ops -

/*Status PromoteNulls(KernelContext* ctx, const ArrayData& cond, const ArrayData& left,
onward

bitmap visitor -

Status PromoteNullsVisitor(KernelContext* ctx, const ArrayData& cond,
onward

Copy link
Member

@lidavidm lidavidm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good! I left some general comments.

As for visitor vs bitmap ops, I think the visitor-based one is fine. It does break down the cases nicely, even if it's a bit verbose.

cpp/src/arrow/compute/api_scalar.h Outdated Show resolved Hide resolved
cpp/src/arrow/compute/kernels/scalar_if_else_test.cc Outdated Show resolved Hide resolved
cpp/src/arrow/compute/kernels/scalar_if_else_test.cc Outdated Show resolved Hide resolved
cpp/src/arrow/compute/kernels/scalar_if_else_test.cc Outdated Show resolved Hide resolved
output->buffers[0]->mutable_data());
break;
case COND_ALL_VALID: // = 1
// out_valid = 0 --> nothing to do; but requires out_valid to be a all-zero buffer
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AllocateBitmap doesn't zero the allocation

/// \brief Allocate buffer for bitmap from the context's memory pool. Like
/// Allocate, the contents of the buffer are not initialized but the last
/// byte is preemptively zeroed to help avoid ASAN or valgrind issues.
Result<std::shared_ptr<ResizableBuffer>> AllocateBitmap(int64_t num_bits);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there is a mismatch in the kernel comment and the impl.

// Since bitmaps are typically written bit by bit, we could leak uninitialized bits.

It looks like it is zeroed out for bitmaps

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, we should probably update comment then. CC @bkietz given KernelContext::AllocateBitmap has to zero the allocation to satisfy Valgrind et al, should we just go ahead and guarantee that it returns a pre-cleared bitmap?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer to leave this for a follow up where we can try to zero only the final byte (as described by the comment) and see if Valgrind is appeased. If not, the comment can be updated

cpp/src/arrow/compute/kernels/scalar_if_else.cc Outdated Show resolved Hide resolved
cpp/src/arrow/compute/kernels/scalar_if_else.cc Outdated Show resolved Hide resolved
cpp/src/arrow/compute/kernels/scalar_if_else_test.cc Outdated Show resolved Hide resolved
// out_buf = ones
ARROW_ASSIGN_OR_RAISE(out_buf, ctx->AllocateBitmap(cond.length));
// filling with UINT8_MAX upto the buffer's size (in bytes)
arrow::compute::internal::SetMemory<UINT8_MAX>(out_buf.get());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could just inline the memset call here - no need to put a helper in a header IMO unless we're going to use it a lot.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please inline the call to memset here

@nirandaperera nirandaperera requested a review from bkietz May 27, 2021 20:32
@nirandaperera nirandaperera marked this pull request as ready for review May 27, 2021 20:43
@nirandaperera
Copy link
Contributor Author

@github-actions autotune

cpp/src/arrow/compute/kernels/scalar_if_else.cc Outdated Show resolved Hide resolved
cpp/src/arrow/compute/kernels/scalar_if_else.cc Outdated Show resolved Hide resolved
cpp/src/arrow/compute/kernels/scalar_if_else.cc Outdated Show resolved Hide resolved
@nirandaperera nirandaperera requested a review from bkietz June 1, 2021 17:18
@nirandaperera
Copy link
Contributor Author

nirandaperera commented Jun 1, 2021

@bkietz @lidavidm I think I have added all the changes requested for this PR so far. Anything else?

Copy link
Member

@bkietz bkietz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just two more improvements

cpp/src/arrow/compute/kernels/scalar_if_else_test.cc Outdated Show resolved Hide resolved
// out_buf = ones
ARROW_ASSIGN_OR_RAISE(out_buf, ctx->AllocateBitmap(cond.length));
// filling with UINT8_MAX upto the buffer's size (in bytes)
arrow::compute::internal::SetMemory<UINT8_MAX>(out_buf.get());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please inline the call to memset here

@jorisvandenbossche jorisvandenbossche changed the title ARROW-10640: [C++] A "where" kernel to combine two arrays based on a mask ARROW-10640: [C++] A, "if_else" ("where") kernel to combine two arrays based on a mask Jun 2, 2021
@jorisvandenbossche
Copy link
Member

I did a quick comparison with np.where (using plain float64 arrays without nulls to have it comparable), and it seems this implementation is already doing quite good compared to numpy (using a release build):

In [19]: N = 10_000_000
    ...: arr1 = np.random.randn(N)
    ...: arr2 = np.random.randn(N)
    ...: mask = np.random.randint(0, 2, N).astype(bool)
    ...: 
    ...: pa_arr1 = pa.array(arr1)
    ...: pa_arr2 = pa.array(arr2)
    ...: pa_mask = pa.array(mask)
    ...: 

In [20]: %timeit np.where(mask, arr1, arr2)
82.3 ms ± 8.76 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [21]: %timeit pc.if_else(pa_mask, pa_arr1, pa_arr2)
50.4 ms ± 6.08 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

@nirandaperera
Copy link
Contributor Author

I did a quick comparison with np.where (using plain float64 arrays without nulls to have it comparable), and it seems this implementation is already doing quite good compared to numpy (using a release build):

In [19]: N = 10_000_000
    ...: arr1 = np.random.randn(N)
    ...: arr2 = np.random.randn(N)
    ...: mask = np.random.randint(0, 2, N).astype(bool)
    ...: 
    ...: pa_arr1 = pa.array(arr1)
    ...: pa_arr2 = pa.array(arr2)
    ...: pa_mask = pa.array(mask)
    ...: 

In [20]: %timeit np.where(mask, arr1, arr2)
82.3 ms ± 8.76 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [21]: %timeit pc.if_else(pa_mask, pa_arr1, pa_arr2)
50.4 ms ± 6.08 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

We may be able to further improve this if we directly use vector operations inside the kernel (I haven't checked the compiled code yet, may be compiler does that already), because if-else use case directly map to mask_move operations in AVX512

Copy link
Member

@bkietz bkietz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Excellent work, thanks for doing this!

@lidavidm
Copy link
Member

lidavidm commented Jun 2, 2021

It looks like there's an actual build failure on CentOS/GCC4.8 (expand "Dump install logs" to get the actual failure):

In file included from /tmp/Rtmpmpy1Y5/file7d77bb9a74/src/arrow/CMakeFiles/arrow_objlib.dir/Unity/unity_17_cxx.cxx:4:0:
/arrow/cpp/src/arrow/compute/kernels/scalar_if_else.cc: In function ‘arrow::Status arrow::compute::{anonymous}::PromoteNullsVisitor(arrow::compute::KernelContext*, const arrow::Datum&, const arrow::Datum&, const arrow::Datum&, arrow::ArrayData*)’:
/arrow/cpp/src/arrow/compute/kernels/scalar_if_else.cc:121:8: error: no matching function for call to ‘arrow::internal::Bitmap::VisitWords(<brace-enclosed initializer list>, arrow::compute::{anonymous}::PromoteNullsVisitor(arrow::compute::KernelContext*, const arrow::Datum&, const arrow::Datum&, const arrow::Datum&, arrow::ArrayData*)::__lambda44)’
       });
        ^
/arrow/cpp/src/arrow/compute/kernels/scalar_if_else.cc:121:8: note: candidate is:
In file included from /arrow/cpp/src/arrow/compute/kernels/scalar_if_else.cc:22:0,
                 from /tmp/Rtmpmpy1Y5/file7d77bb9a74/src/arrow/CMakeFiles/arrow_objlib.dir/Unity/unity_17_cxx.cxx:4:
/arrow/cpp/src/arrow/util/bitmap.h:128:18: note: template<long unsigned int N, class Visitor, class Word> static int64_t arrow::internal::Bitmap::VisitWords(const arrow::internal::Bitmap (&)[N], Visitor&&)
   static int64_t VisitWords(const Bitmap (&bitmaps_arg)[N], Visitor&& visitor) {
                  ^
/arrow/cpp/src/arrow/util/bitmap.h:128:18: note:   template argument deduction/substitution failed:
In file included from /tmp/Rtmpmpy1Y5/file7d77bb9a74/src/arrow/CMakeFiles/arrow_objlib.dir/Unity/unity_17_cxx.cxx:4:0:
/arrow/cpp/src/arrow/compute/kernels/scalar_if_else.cc:121:8: note:   couldn't deduce template parameter ‘N’
       });
        ^
/arrow/cpp/src/arrow/compute/kernels/scalar_if_else.cc:127:12: error: no matching function for call to ‘arrow::internal::Bitmap::VisitWords(<brace-enclosed initializer list>, arrow::compute::{anonymous}::PromoteNullsVisitor(arrow::compute::KernelContext*, const arrow::Datum&, const arrow::Datum&, const arrow::Datum&, arrow::ArrayData*)::__lambda45)’
           });
            ^
/arrow/cpp/src/arrow/compute/kernels/scalar_if_else.cc:127:12: note: candidate is:
In file included from /arrow/cpp/src/arrow/compute/kernels/scalar_if_else.cc:22:0,
                 from /tmp/Rtmpmpy1Y5/file7d77bb9a74/src/arrow/CMakeFiles/arrow_objlib.dir/Unity/unity_17_cxx.cxx:4:
/arrow/cpp/src/arrow/util/bitmap.h:128:18: note: template<long unsigned int N, class Visitor, class Word> static int64_t arrow::internal::Bitmap::VisitWords(const arrow::internal::Bitmap (&)[N], Visitor&&)
   static int64_t VisitWords(const Bitmap (&bitmaps_arg)[N], Visitor&& visitor) {
            ^
/arrow/cpp/src/arrow/compute/kernels/scalar_if_else.cc:157:12: note: candidate is:
In file included from /arrow/cpp/src/arrow/compute/kernels/scalar_if_else.cc:22:0,
                 from /tmp/Rtmpmpy1Y5/file7d77bb9a74/src/arrow/CMakeFiles/arrow_objlib.dir/Unity/unity_17_cxx.cxx:4:
/arrow/cpp/src/arrow/util/bitmap.h:128:18: note: template<long unsigned int N, class Visitor, class Word> static int64_t arrow::internal::Bitmap::VisitWords(const arrow::internal::Bitmap (&)[N], Visitor&&)
   static int64_t VisitWords(const Bitmap (&bitmaps_arg)[N], Visitor&& visitor) {
                  ^
/arrow/cpp/src/arrow/util/bitmap.h:128:18: note:   template argument deduction/substitution failed:
In file included from /tmp/Rtmpmpy1Y5/file7d77bb9a74/src/arrow/CMakeFiles/arrow_objlib.dir/Unity/unity_17_cxx.cxx:4:0:
/arrow/cpp/src/arrow/compute/kernels/scalar_if_else.cc:157:12: note:   couldn't deduce template parameter ‘N’
           });
            ^
/arrow/cpp/src/arrow/compute/kernels/scalar_if_else.cc:164:12: error: no matching function for call to ‘arrow::internal::Bitmap::VisitWords(<brace-enclosed initializer list>, arrow::compute::{anonymous}::PromoteNullsVisitor(arrow::compute::KernelContext*, const arrow::Datum&, const arrow::Datum&, const arrow::Datum&, arrow::ArrayData*)::__lambda50)’
           });
            ^
/arrow/cpp/src/arrow/compute/kernels/scalar_if_else.cc:164:12: note: candidate is:
In file included from /arrow/cpp/src/arrow/compute/kernels/scalar_if_else.cc:22:0,
                 from /tmp/Rtmpmpy1Y5/file7d77bb9a74/src/arrow/CMakeFiles/arrow_objlib.dir/Unity/unity_17_cxx.cxx:4:
/arrow/cpp/src/arrow/util/bitmap.h:128:18: note: template<long unsigned int N, class Visitor, class Word> static int64_t arrow::internal::Bitmap::VisitWords(const arrow::internal::Bitmap (&)[N], Visitor&&)
   static int64_t VisitWords(const Bitmap (&bitmaps_arg)[N], Visitor&& visitor) {
                  ^
/arrow/cpp/src/arrow/util/bitmap.h:128:18: note:   template argument deduction/substitution failed:
In file included from /tmp/Rtmpmpy1Y5/file7d77bb9a74/src/arrow/CMakeFiles/arrow_objlib.dir/Unity/unity_17_cxx.cxx:4:0:
/arrow/cpp/src/arrow/compute/kernels/scalar_if_else.cc:164:12: note:   couldn't deduce template parameter ‘N’
           });
            ^
/arrow/cpp/src/arrow/compute/kernels/scalar_if_else.cc:171:27: error: no matching function for call to ‘arrow::internal::Bitmap::VisitWords(<brace-enclosed initializer list>, arrow::compute::{anonymous}::PromoteNullsVisitor(arrow::compute::KernelContext*, const arrow::Datum&, const arrow::Datum&, const arrow::Datum&, arrow::ArrayData*)::__lambda51)’
                          });
                           ^
/arrow/cpp/src/arrow/compute/kernels/scalar_if_else.cc:171:27: note: candidate is:
In file included from /arrow/cpp/src/arrow/compute/kernels/scalar_if_else.cc:22:0,
                 from /tmp/Rtmpmpy1Y5/file7d77bb9a74/src/arrow/CMakeFiles/arrow_objlib.dir/Unity/unity_17_cxx.cxx:4:
/arrow/cpp/src/arrow/util/bitmap.h:128:18: note: template<long unsigned int N, class Visitor, class Word> static int64_t arrow::internal::Bitmap::VisitWords(const arrow::internal::Bitmap (&)[N], Visitor&&)
   static int64_t VisitWords(const Bitmap (&bitmaps_arg)[N], Visitor&& visitor) {
                  ^
/arrow/cpp/src/arrow/util/bitmap.h:128:18: note:   template argument deduction/substitution failed:
In file included from /tmp/Rtmpmpy1Y5/file7d77bb9a74/src/arrow/CMakeFiles/arrow_objlib.dir/Unity/unity_17_cxx.cxx:4:0:
/arrow/cpp/src/arrow/compute/kernels/scalar_if_else.cc:171:27: note:   couldn't deduce template parameter ‘N’
                          });

@nirandaperera
Copy link
Contributor Author

It looks like there's an actual build failure on CentOS/GCC4.8 (expand "Dump install logs" to get the actual failure):

In file included from /tmp/Rtmpmpy1Y5/file7d77bb9a74/src/arrow/CMakeFiles/arrow_objlib.dir/Unity/unity_17_cxx.cxx:4:0:
/arrow/cpp/src/arrow/compute/kernels/scalar_if_else.cc: In function ‘arrow::Status arrow::compute::{anonymous}::PromoteNullsVisitor(arrow::compute::KernelContext*, const arrow::Datum&, const arrow::Datum&, const arrow::Datum&, arrow::ArrayData*)’:
/arrow/cpp/src/arrow/compute/kernels/scalar_if_else.cc:121:8: error: no matching function for call to ‘arrow::internal::Bitmap::VisitWords(<brace-enclosed initializer list>, arrow::compute::{anonymous}::PromoteNullsVisitor(arrow::compute::KernelContext*, const arrow::Datum&, const arrow::Datum&, const arrow::Datum&, arrow::ArrayData*)::__lambda44)’
       });
        ^
/arrow/cpp/src/arrow/compute/kernels/scalar_if_else.cc:121:8: note: candidate is:
In file included from /arrow/cpp/src/arrow/compute/kernels/scalar_if_else.cc:22:0,
                 from /tmp/Rtmpmpy1Y5/file7d77bb9a74/src/arrow/CMakeFiles/arrow_objlib.dir/Unity/unity_17_cxx.cxx:4:
/arrow/cpp/src/arrow/util/bitmap.h:128:18: note: template<long unsigned int N, class Visitor, class Word> static int64_t arrow::internal::Bitmap::VisitWords(const arrow::internal::Bitmap (&)[N], Visitor&&)
   static int64_t VisitWords(const Bitmap (&bitmaps_arg)[N], Visitor&& visitor) {
                  ^
/arrow/cpp/src/arrow/util/bitmap.h:128:18: note:   template argument deduction/substitution failed:
In file included from /tmp/Rtmpmpy1Y5/file7d77bb9a74/src/arrow/CMakeFiles/arrow_objlib.dir/Unity/unity_17_cxx.cxx:4:0:
/arrow/cpp/src/arrow/compute/kernels/scalar_if_else.cc:121:8: note:   couldn't deduce template parameter ‘N’
       });
        ^
/arrow/cpp/src/arrow/compute/kernels/scalar_if_else.cc:127:12: error: no matching function for call to ‘arrow::internal::Bitmap::VisitWords(<brace-enclosed initializer list>, arrow::compute::{anonymous}::PromoteNullsVisitor(arrow::compute::KernelContext*, const arrow::Datum&, const arrow::Datum&, const arrow::Datum&, arrow::ArrayData*)::__lambda45)’
           });
            ^
/arrow/cpp/src/arrow/compute/kernels/scalar_if_else.cc:127:12: note: candidate is:
In file included from /arrow/cpp/src/arrow/compute/kernels/scalar_if_else.cc:22:0,
                 from /tmp/Rtmpmpy1Y5/file7d77bb9a74/src/arrow/CMakeFiles/arrow_objlib.dir/Unity/unity_17_cxx.cxx:4:
/arrow/cpp/src/arrow/util/bitmap.h:128:18: note: template<long unsigned int N, class Visitor, class Word> static int64_t arrow::internal::Bitmap::VisitWords(const arrow::internal::Bitmap (&)[N], Visitor&&)
   static int64_t VisitWords(const Bitmap (&bitmaps_arg)[N], Visitor&& visitor) {
            ^
/arrow/cpp/src/arrow/compute/kernels/scalar_if_else.cc:157:12: note: candidate is:
In file included from /arrow/cpp/src/arrow/compute/kernels/scalar_if_else.cc:22:0,
                 from /tmp/Rtmpmpy1Y5/file7d77bb9a74/src/arrow/CMakeFiles/arrow_objlib.dir/Unity/unity_17_cxx.cxx:4:
/arrow/cpp/src/arrow/util/bitmap.h:128:18: note: template<long unsigned int N, class Visitor, class Word> static int64_t arrow::internal::Bitmap::VisitWords(const arrow::internal::Bitmap (&)[N], Visitor&&)
   static int64_t VisitWords(const Bitmap (&bitmaps_arg)[N], Visitor&& visitor) {
                  ^
/arrow/cpp/src/arrow/util/bitmap.h:128:18: note:   template argument deduction/substitution failed:
In file included from /tmp/Rtmpmpy1Y5/file7d77bb9a74/src/arrow/CMakeFiles/arrow_objlib.dir/Unity/unity_17_cxx.cxx:4:0:
/arrow/cpp/src/arrow/compute/kernels/scalar_if_else.cc:157:12: note:   couldn't deduce template parameter ‘N’
           });
            ^
/arrow/cpp/src/arrow/compute/kernels/scalar_if_else.cc:164:12: error: no matching function for call to ‘arrow::internal::Bitmap::VisitWords(<brace-enclosed initializer list>, arrow::compute::{anonymous}::PromoteNullsVisitor(arrow::compute::KernelContext*, const arrow::Datum&, const arrow::Datum&, const arrow::Datum&, arrow::ArrayData*)::__lambda50)’
           });
            ^
/arrow/cpp/src/arrow/compute/kernels/scalar_if_else.cc:164:12: note: candidate is:
In file included from /arrow/cpp/src/arrow/compute/kernels/scalar_if_else.cc:22:0,
                 from /tmp/Rtmpmpy1Y5/file7d77bb9a74/src/arrow/CMakeFiles/arrow_objlib.dir/Unity/unity_17_cxx.cxx:4:
/arrow/cpp/src/arrow/util/bitmap.h:128:18: note: template<long unsigned int N, class Visitor, class Word> static int64_t arrow::internal::Bitmap::VisitWords(const arrow::internal::Bitmap (&)[N], Visitor&&)
   static int64_t VisitWords(const Bitmap (&bitmaps_arg)[N], Visitor&& visitor) {
                  ^
/arrow/cpp/src/arrow/util/bitmap.h:128:18: note:   template argument deduction/substitution failed:
In file included from /tmp/Rtmpmpy1Y5/file7d77bb9a74/src/arrow/CMakeFiles/arrow_objlib.dir/Unity/unity_17_cxx.cxx:4:0:
/arrow/cpp/src/arrow/compute/kernels/scalar_if_else.cc:164:12: note:   couldn't deduce template parameter ‘N’
           });
            ^
/arrow/cpp/src/arrow/compute/kernels/scalar_if_else.cc:171:27: error: no matching function for call to ‘arrow::internal::Bitmap::VisitWords(<brace-enclosed initializer list>, arrow::compute::{anonymous}::PromoteNullsVisitor(arrow::compute::KernelContext*, const arrow::Datum&, const arrow::Datum&, const arrow::Datum&, arrow::ArrayData*)::__lambda51)’
                          });
                           ^
/arrow/cpp/src/arrow/compute/kernels/scalar_if_else.cc:171:27: note: candidate is:
In file included from /arrow/cpp/src/arrow/compute/kernels/scalar_if_else.cc:22:0,
                 from /tmp/Rtmpmpy1Y5/file7d77bb9a74/src/arrow/CMakeFiles/arrow_objlib.dir/Unity/unity_17_cxx.cxx:4:
/arrow/cpp/src/arrow/util/bitmap.h:128:18: note: template<long unsigned int N, class Visitor, class Word> static int64_t arrow::internal::Bitmap::VisitWords(const arrow::internal::Bitmap (&)[N], Visitor&&)
   static int64_t VisitWords(const Bitmap (&bitmaps_arg)[N], Visitor&& visitor) {
                  ^
/arrow/cpp/src/arrow/util/bitmap.h:128:18: note:   template argument deduction/substitution failed:
In file included from /tmp/Rtmpmpy1Y5/file7d77bb9a74/src/arrow/CMakeFiles/arrow_objlib.dir/Unity/unity_17_cxx.cxx:4:0:
/arrow/cpp/src/arrow/compute/kernels/scalar_if_else.cc:171:27: note:   couldn't deduce template parameter ‘N’
                          });

Ah! thanks @lidavidm I missed this... it seems to be a gcc 4.x thing, isn't it.

BTW @bkietz should I add string type support to this as well, or can I leave it for later development?

@jorisvandenbossche
Copy link
Member

should I add string type support to this as well, or can I leave it for later development?

I think it is important to add support for strings as well, but it's probably a good idea to leave that for a follow-up PR so we can get this merged? (I can imagine the implementation to be a bit different / more complex for variable length array elements)

@lidavidm
Copy link
Member

lidavidm commented Jun 3, 2021

I agree, and also Niranda already filed ARROW-12955 to take care of that followup.

Copy link
Member

@lidavidm lidavidm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like that fixed the builds, and the remaining failures are not relevant.

@lidavidm lidavidm closed this in 5baebba Jun 3, 2021
@ianmcook ianmcook changed the title ARROW-10640: [C++] A, "if_else" ("where") kernel to combine two arrays based on a mask ARROW-10640: [C++] An "if_else" kernel to combine two arrays based on a mask Jun 3, 2021
michalursa pushed a commit to michalursa/arrow that referenced this pull request Jun 13, 2021
…s based on a mask

Adding a preliminary impl for an `if_else(cond: Datum, left: Datum, right: Datum)` function. It works as follows,
```python
def if_else(cond, left, right):
    for c, true_val, false_val in zip(cond, left, right):
        if c:
            yield true_val
        else:
            yield false_val
```
`null` values will be promoted to the output.

Closes apache#10410 from nirandaperera/ARROW-10640

Authored-by: niranda perera <niranda.perera@gmail.com>
Signed-off-by: David Li <li.davidm96@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants