I don't know R, but, after reading the documentation, it looks like the following will do the trick (albeit a little less general)
def scale(y, c=True, sc=True): x = y.copy() if c: x -= x.mean() if sc and c: x /= x.std() elif sc: x /= np.sqrt(x.pow(2).sum().div(x.count() - 1)) return x
For a more general version, you probably need to do a type / length check.
EDIT: Added denominator explanation in elif sc: section elif sc:
From the docs R:
... If 'scale' is 'TRUE' then scaling is done by dividing the (centered) columns of 'x' by their standard deviations if 'center' is 'TRUE', and the root mean square otherwise. If 'scale' is 'FALSE', no scaling is done. The root-mean-square for a (possibly centered) column is defined as sqrt(sum(x^2)/(n-1)), where x is a vector of the non-missing values and n is the number of non-missing values. In the case 'center = TRUE', this is the same as the standard deviation, but in general it is not.
The line np.sqrt(x.pow(2).sum().div(x.count() - 1)) calculates the average square of the root using the definition using the first squaring x (the pow method), then summing the lines, and then dividing by NaN counters in each column ( count ).
As a side note, the reason I just didn’t just calculate the RMS after centering is because the std method calls bottleneck to calculate this expression faster in this special case, when you want to calculate the standard deviation and not the more general RMS.
Instead, you could calculate the RMS after centering, maybe worth the benchmark, because now I'm writing this, I'm not really sure what is faster, and I did not compare it.