xtensor and numpy are very different libraries in their internal semantics. While xtensor
is a lazy expression system, Numpy manipulates in-memory containers, however, similarities in
APIs are obvious. See e.g. the numpy to xtensor cheat sheet.

And this page tracks the subtle differences of behavior of numpy and xtensor.

With numpy, 0-D arrays are nearly indistinguishable from scalars. This led to some issues w.r.t.
universal functions returning scalars with 0-D array inputs instead of actual arrays…

In xtensor, 0-D expressions are not implicitely convertible to scalar values. Values held by 0-D
expressions can be accessed in the same way as values of higher dimensional arrays, that is with
operator[], operator() and element.

Support of missing values in numpy can be emulated with the masked array module,
which provides a means to handle arrays that have missing or invalid data.

Support of missing values in xtensor is done through a notion of optional values, implemented in xoptional<T,B>, which serves both as a value type for container and as a reference proxy for optimized storage types. See the section of the documentation on Missing values.