<h3 dir="auto">Describe your issue.</h3>
<p dir="auto">Currently, applying the <code class="notranslate">**</code> operator to a sparse array implements the <code class="notranslate">numpy.linalg.matrix_power</code> function. This is not compatible with the <code class="notranslate">np.array</code> implementation of <code class="notranslate">**</code>, which does element-wise power. This should be fixed as part of the migration from sparse "matrices" to sparse "arrays". Additionally, the <code class="notranslate">matrix_power</code> function should then also be included in the <code class="notranslate">sparse.linalg</code> package.</p>
<h3 dir="auto">Reproducing Code Example</h3>
<div class="highlight highlight-source-python notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="from scipy.sparse import csr_array, random

A = csr_array(random(5,5,0.1))
print(A.A)  
print((A**2).A)  #This does matrix_power, eventhough it is initialised as a sparse array (not a matrix)
print((A.A)**2)  #This does element-wise power, since it is a numpy array"><pre class="notranslate"><span class="pl-k">from</span> <span class="pl-s1">scipy</span>.<span class="pl-s1">sparse</span> <span class="pl-k">import</span> <span class="pl-s1">csr_array</span>, <span class="pl-s1">random</span>

<span class="pl-v">A</span> <span class="pl-c1">=</span> <span class="pl-en">csr_array</span>(<span class="pl-en">random</span>(<span class="pl-c1">5</span>,<span class="pl-c1">5</span>,<span class="pl-c1">0.1</span>))
<span class="pl-en">print</span>(<span class="pl-v">A</span>.<span class="pl-v">A</span>)  
<span class="pl-en">print</span>((<span class="pl-v">A</span><span class="pl-c1">**</span><span class="pl-c1">2</span>).<span class="pl-v">A</span>)  <span class="pl-c">#This does matrix_power, eventhough it is initialised as a sparse array (not a matrix)</span>
<span class="pl-en">print</span>((<span class="pl-v">A</span>.<span class="pl-v">A</span>)<span class="pl-c1">**</span><span class="pl-c1">2</span>)  <span class="pl-c">#This does element-wise power, since it is a numpy array</span></pre></div>
<h3 dir="auto">Error message</h3>
<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="N/A"><pre class="notranslate">N/A</pre></div>
<h3 dir="auto">SciPy/NumPy/Python version information</h3>
<p dir="auto">1.8.0 1.20.3 sys.version_info(major=3, minor=9, micro=7, releaselevel='final', serial=0)</p>
<p dir="auto">In <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="834786139" data-permission-text="Title is private" data-url="https://github.com/scipy/scipy/issues/13699" data-hovercard-type="pull_request" data-hovercard-url="/scipy/scipy/pull/13699/hovercard" href="https://github.com/scipy/scipy/pull/13699">#13699</a>, I am implementing the fitting of distributions to censored data.   To represent censored data, I created a fairly simple class called <code class="notranslate">CensoredData</code>, and updated the <code class="notranslate">fit</code> method of the univariate continuous distributions to be able to handle an instance of the class.  There have been questions about the API for representing censored data in the PR.  Instead of having that discussion in the PR (where we also discuss implementation details), it seems cleaner to break out the API discussion to its own issue.</p>
<p dir="auto">The wikipedia article <a href="https://en.wikipedia.org/wiki/Censoring_(statistics)" rel="nofollow">Censoring (statistics)</a> provides an overview of what censored data is.  In the <code class="notranslate">CensoredData</code> class, we want to represent a data set that contains a mix of regular (i.e. not censored) data, right-censored data, left-censored data and interval-censored data.  The first three cases require a single number for each data point, while the last, interval-censored, requires two values to define the interval.</p>
<p dir="auto">A common case of censoring is a data set that is a mix of regular values and censored values that all have the same type.  For example, the data shown in <a href="https://support.sas.com/documentation/cdl/en/qcug/63922/HTML/default/viewer.htm#qcug_reliability_sect004.htm" rel="nofollow">this page</a> are either not censored or right censored.  The same is true for the first example in <a href="http://www.ams.sunysb.edu/~zhu/ams588/Lecture_3_likelihood.pdf" rel="nofollow">this set of slides</a>.  It would be nice if the API makes it easy to create an instance of <code class="notranslate">CensoredData</code> for such data sets.</p>
<p dir="auto">The following are two possible constructors for the <code class="notranslate">CensoredData</code> class.</p>
<p dir="auto"><em>Alternative 1: CensoredData(lower, upper)</em></p>
<p dir="auto">At the time of writing this comment, the <code class="notranslate">CensoredData</code> class has a constructor with the signature <code class="notranslate">__init__(self, lower, upper)</code>, where <code class="notranslate">lower</code> and <code class="notranslate">upper</code> are expected to be 1D arrays of numbers.  A number can be ±inf.  This API follows from the fact that we can represent all four cases (not censored, left-censored, right-censored or interval-censored) as an interval, if we allow ±inf as an end point, and if we interpret an interval of length 0 as an uncensored point.  The meaning of those points in the interval-censored case is as expected.  For a left-censored data point, the left value of the pair is set to -inf (i.e. the pair [-inf, 1] represents a left-censored value that is less than 1).  Likewise, for a right-censored data point, the right value is set to +inf.  For data points that are not censored, the two values are set to the same value (i.e. it is an "interval" with length 0).</p>
<p dir="auto">Above I mentioned the common case of data that is a mix of uncensored and right-censored points.  A simple example in the docstring for <code class="notranslate">CensoredData</code> has four regular values, [13, 22, 17, 15], and two right-censored values, [20, 18].  To create a <code class="notranslate">CensoredData</code> instance for this data using the constructor, one would write:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="CensoredData(lower=[13, 22, 17, 15, 20, 18], upper=[13, 22, 17, 15, np.inf, np.inf])"><pre class="notranslate"><code class="notranslate">CensoredData(lower=[13, 22, 17, 15, 20, 18], upper=[13, 22, 17, 15, np.inf, np.inf])
</code></pre></div>
<p dir="auto">The first four pairs <code class="notranslate">(lower[i], upper[i])</code> represent the uncensored data points, and the last two represent the right-censored data.</p>
<p dir="auto">This API is very similar to the API provided by the R function <a href="https://www.rdocumentation.org/packages/fitdistrplus/versions/1.1-3/topics/fitdistcens" rel="nofollow"><code class="notranslate">fitdistcens</code></a> that is part of the <a href="https://www.rdocumentation.org/packages/fitdistrplus/versions/1.1-3" rel="nofollow"><code class="notranslate">fitdistrplus</code></a> package.  <code class="notranslate">fitdistcens</code> expects the censored data set to be represented as a data frame with two columns, named <code class="notranslate">left</code> and <code class="notranslate">right</code>.  The interpretion of the values in those columns is the same as that used in the current implemention of <code class="notranslate">CensoredData</code>, except that the R function uses <code class="notranslate">NA</code> instead of ±inf to indicate that a data point is left- or right-censored.   The above example in R would be</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="data = data.frame(left=c(13, 22, 17, 15, 20, 18), right=c(13, 22, 17, 15, NA, NA))"><pre class="notranslate"><code class="notranslate">data = data.frame(left=c(13, 22, 17, 15, 20, 18), right=c(13, 22, 17, 15, NA, NA))
</code></pre></div>
<p dir="auto">To make it a bit easier to create data sets of this form, <code class="notranslate">CensoredData</code> has two alternative constructors implemented as class methods, <code class="notranslate">left_censored</code> and <code class="notranslate">right_censored</code>.  These take two arguments, a 1D array <code class="notranslate">x</code> of numbers and a boolean array of the same length that indicates if the corresponding value in <code class="notranslate">x</code> is censored.  With the <code class="notranslate">right_censored</code> method, the example above is created with</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="CensoredData.right_censored(13, 22, 17, 15, 20, 18], [False, False, False, False, True, True])"><pre class="notranslate"><code class="notranslate">CensoredData.right_censored(13, 22, 17, 15, 20, 18], [False, False, False, False, True, True])
</code></pre></div>
<p dir="auto">So instead of having to create a copy of the values and assign <code class="notranslate">inf</code> where appropriate, the user supplies a boolean array.  A 0/1 flag is pretty common in the examples that I've found on the web where the data is shown in a textual format, so it is likely that such boolean array would be easily created when, say, reading the data from a file.</p>
<p dir="auto"><em>Alternative 2: CensoredData(x=None, left=None, right=None, intervals=None)</em></p>
<p dir="auto">This is an alternative API, in which the constructor has a parameter for each type of censoring.  The parameters are</p>
<p dir="auto"><code class="notranslate">x</code>: a 1D array of uncensored measurements<br>
<code class="notranslate">left</code>: a 1D array of left-censored measurements<br>
<code class="notranslate">right</code>: a 1D array of right-censored measurements<br>
<code class="notranslate">intervals</code>: a 2D array with shape (m, 2) containing the intervals for <code class="notranslate">m</code> interval-censored values</p>
<p dir="auto">The nice thing about this API is its explicitness, and that it doesn't require the user to use ±inf to create left- or right-censored values. The simple example given above can be represented as</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="CensoredData(x=[13, 22, 17, 15], right=[20, 18])"><pre class="notranslate"><code class="notranslate">CensoredData(x=[13, 22, 17, 15], right=[20, 18])
</code></pre></div>
<p dir="auto">That is a clean API for creating a right-censored data set, so the convenience provided by the alternative constructor <code class="notranslate">CensoredData.right_censored</code> is less important.  If we went with this API, I would probably remove the <code class="notranslate">left_censored</code> and <code class="notranslate">right_censored</code> methods.</p>
<p dir="auto">There is redundancy here, because (assuming we interpret intervals containing ±inf and intervals with length 0 the same as they are interpreted in the other API), any value that can be represent with <code class="notranslate">x</code>, <code class="notranslate">left</code> or <code class="notranslate">right</code> can also be represented as an interval.  That is, the right-censored example could also be represented as</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="CensoredData(intervals=[[13, 13], [22, 22], [17, 17], [15, 15], [20, np.inf], [20, np.inf]])"><pre class="notranslate"><code class="notranslate">CensoredData(intervals=[[13, 13], [22, 22], [17, 17], [15, 15], [20, np.inf], [20, np.inf]])
</code></pre></div>
<p dir="auto">But that isn't necessarily a problem.</p>