Numpy变量切片大小(可能为零)

huangapple go评论76阅读模式
英文:

Numpy variable slice size (possibly zero)

问题

以下是您要翻译的内容:

"假设我有一些时间序列数据:"

import numpy as np
import matplotlib.pyplot as plt
np.random.seed(42)
x = np.linspace(0, 10, num=100)
time_series = np.sin(x) + np.random.random(100)
plt.plot(x, time_series)

Numpy变量切片大小(可能为零)

如果我想要将时间序列“延迟”一段时间,我可以这样做:

delay = 10
x_delayed = x[delay:]
time_series_delayed = time_series[:-delay]

plt.plot(x, time_series, label='original')
plt.plot(x_delayed, time_series_delayed, label='delayed')
plt.legend()

Numpy变量切片大小(可能为零)

这一切都很好,但我希望在保持代码整洁的同时允许delay为零。目前,我会因为切片my_arr[:-0]的评估结果仅为my_arr[:0]而出现错误,而这将始终是空切片,而不是完整的数组。

>>> time_series[:-0]
array([], dtype=float64)

这意味着,如果我想要表示延迟为零等同于原始数组的想法,我必须每次使用切片都进行特殊处理。这很繁琐且容易出错:

# 为负延迟、零延迟和正延迟制作3个图
for delay in (0, 5, -5):

    if delay > 0:
        x_delayed = x[delay:]
        time_series_delayed = time_series[:-delay]

    elif delay < 0:
        # 负延迟是正延迟的补集
        x_delayed = x[:delay]
        time_series_delayed = time_series[-delay:]

    else:
        # 零延迟只是复制数组
        x_delayed = x[:]
        time_series_delayed = time_series[:]
    # 将延迟的时间序列添加到图中
    plt.plot(
        x_delayed, 
        time_series_delayed, 
        label=f'delay={delay}',
        # 更改alpha以减少混杂
        alpha=1 if delay == 0 else 0.3
    )
plt.legend()

Numpy变量切片大小(可能为零)

我已经看过numpy切片对象和np._s,但似乎无法弄清楚。

是否有一种巧妙/Pythonic的方法来表示延迟为零就是原始数组?

英文:

Lets say I've got some time series data:

import numpy as np
import matplotlib.pyplot as plt
np.random.seed(42)
x = np.linspace(0, 10, num=100)
time_series = np.sin(x) + np.random.random(100)
plt.plot(x, time_series)

Numpy变量切片大小(可能为零)

If I want to 'delay' the time series by some amount, I can do this:

delay = 10
x_delayed = x[delay:]
time_series_delayed = time_series[:-delay]

plt.plot(x, time_series, label=&#39;original&#39;)
plt.plot(x_delayed, time_series_delayed, label=&#39;delayed&#39;)
plt.legend()

Numpy变量切片大小(可能为零)

This is all well and good, but I want to keep the code clean while still allowing delay to be zero. As it stands, I get an error because the slice my_arr[:-0] just evaluates to my_arr[:0] which will always be the empty slice, instead of the full array.

&gt;&gt;&gt; time_series[:-0]
array([], dtype=float64)

This means that if I want to encode the idea that a delay of zero is identical to the original array, I have to special case every single time I use the slice. This is tedious and error prone:

# Make 3 plots, for negative, zero, and positive delays
for delay in (0, 5, -5):

    if delay &gt; 0:
        x_delayed = x[delay:]
        time_series_delayed = time_series[:-delay]

    elif delay &lt; 0:
        # Negative delay is the complement of positive delay
        x_delayed = x[:delay]
        time_series_delayed = time_series[-delay:]

    else:
        # Zero delay just copies the array
        x_delayed = x[:]
        time_series_delayed = time_series[:]
    # Add the delayed time series to the plot
    plt.plot(
        x_delayed, 
        time_series_delayed, 
        label=f&#39;delay={delay}&#39;,
        # change the alpha to make things less cluttered
        alpha=1 if delay == 0 else 0.3
    )
plt.legend()

Numpy变量切片大小(可能为零)

I've had a look at the numpy slicing object and np._s, but I can't seem to figure it out.

Is there a neat/pythonic way of encoding the idea that a delay of zero is the original array?

答案1

得分: 1

以下是您要翻译的内容:

"I don't know if this is as neat as one might like, but you can make use of the way Python treats truthiness and falseness, so that i or x is equal to x if i is 0, but i if i is any other integer.

So you could replace the various branches of your conditional with just:

time_series_delayed = time_series[:-delay or len(time_series)]

When delay is 0, this evaluates to time_series[:len(time_series)] which is the same as time_series itself.

As a quick demonstration:

time_series = list(range(10))

def f(i):
    return time_series[:-i or len(time_series)]

print(time_series)
for n in (2, 1, 0):
    print(f"{n}: {f(n)}")

prints:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
2: [0, 1, 2, 3, 4, 5, 6, 7]
1: [0, 1, 2, 3, 4, 5, 6, 7, 8]
0: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
英文:

I don't know if this is as neat as one might like, but you can make use of the way Python treates truthiness and falsiness, so that i or x is equal to x if i is 0, but i if i is any other integer.

So you could replace the various branches of your conditional with just:

time_series_delayed = time_series[:-delay or len(time_series)]

When delay is 0, this evaluates to time_series[:len(time_series)] which is the same as time_series itself.

As a quick demonstration:

time_series = list(range(10))

def f(i):
	return time_series[:-i or len(time_series)]

print(time_series)
for n in (2, 1, 0):
	print(f&quot;{n}: {f(n)}&quot;)

prints:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
2: [0, 1, 2, 3, 4, 5, 6, 7]
1: [0, 1, 2, 3, 4, 5, 6, 7, 8]
0: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

答案2

得分: 0

以下是您要翻译的内容:

"The solution I went with uses the fact that my_arr[2:] is equivalent to my_arr[2:None]:

arr[(d if d &gt; 0 else None):(d if d &lt; 0 else None)]

A bit more readable:

arr = [0, 1, 2, 3, 4, 5]
delay = 3

start_delay = delay if delay &gt; 0 else None
finish_delay = delay if delay &lt; 0 else None

delayed_arr = arr[start_delay:finish_delay]

Wrapped up in a nice method and with some assertions to show it works:

def delay_array(array, delay):
    &quot;&quot;&quot;Delays the values in `array` by the amount `delay`.

    Regular slicing struggles with this since negative slicing (which goes from
    the end of the array) and positive slicing (going from the front of the
    array) meet at zero and don&#39;t play nicely.

    We use the fact that Python&#39;s slicing syntax treats `None` as though it
    didn&#39;t exist, so `arr[2:]` is equivalent to `arr[2:None]`.

    This can be used on numpy arrays, but also works on native python lists.
    &quot;&quot;&quot;
    start_index = delay if delay &gt; 0 else None
    finish_index = delay if delay &lt; 0 else None
    return array[start_index:finish_index]

arr = [0, 1, 2, 3, 4, 5]
# Zero delay results in the same array
assert delay_array(arr,  0) == [0, 1, 2, 3, 4, 5]

# Delay greater/less than zero removes `delay` elements from the front/back
# of the array
assert delay_array(arr, +3) == [         3, 4, 5]
assert delay_array(arr, -3) == [0, 1, 2,        ]

# A delay longer than the array results in an empty array
assert delay_array(arr, +6) == []
assert delay_array(arr, -6) == []

And to cap it all off:

def delay_array(array, delay):
    start_index = delay if delay &gt; 0 else None
    finish_index = delay if delay &lt; 0 else None
    return array[start_index:finish_index]

np.random.seed(42)
x = np.linspace(0, 10, num=100)
time_series = np.sin(x) + np.random.random(100)

for delay in (0, 5, -5):
    x_delayed = delay_array(x, delay)
    time_series_delayed = delay_array(time_series, -delay)
    plt.plot(
        x_delayed, 
        time_series_delayed, 
        label=f&#39;delay={delay}&#39;,
        alpha=1 if delay == 0 else 0.3
    )
plt.legend()

Numpy变量切片大小(可能为零)

英文:

The solution I went with uses the fact that my_arr[2:] is equivalent to my_arr[2:None]:

arr[(d if d &gt; 0 else None):(d if d &lt; 0 else None)]

A bit more readable:

arr = [0, 1, 2, 3, 4, 5]
delay = 3

start_delay = delay if delay &gt; 0 else None
finish_delay = delay if delay &lt; 0 else None

delayed_arr = arr[start_delay:finish_delay]

Wrapped up in a nice method and with some assertions to show it works:

def delay_array(array, delay):
    &quot;&quot;&quot;Delays the values in `array` by the amount `delay`.

    Regular slicing struggles with this since negative slicing (which goes from
    the end of the array) and positive slicing (going from the front of the
    array) meet at zero and don&#39;t play nicely.

    We use the fact that Python&#39;s slicing syntax treats `None` as though it
    didn&#39;t exist, so `arr[2:]` is equivalent to `arr[2:None]`.

    This can be used on numpy arrays, but also works on native python lists.
    &quot;&quot;&quot;
    start_index = delay if delay &gt; 0 else None
    finish_index = delay if delay &lt; 0 else None
    return array[start_index:finish_index]

arr = [0, 1, 2, 3, 4, 5]
# Zero delay results in the same array
assert delay_array(arr,  0) == [0, 1, 2, 3, 4, 5]

# Delay greater/less than zero removes `delay` elements from the front/back
# of the array
assert delay_array(arr, +3) == [         3, 4, 5]
assert delay_array(arr, -3) == [0, 1, 2,        ]

# A delay longer than the array results in an empty array
assert delay_array(arr, +6) == []
assert delay_array(arr, -6) == []

And to cap it all off:

def delay_array(array, delay):
    start_index = delay if delay &gt; 0 else None
    finish_index = delay if delay &lt; 0 else None
    return array[start_index:finish_index]

np.random.seed(42)
x = np.linspace(0, 10, num=100)
time_series = np.sin(x) + np.random.random(100)

for delay in (0, 5, -5):
    x_delayed = delay_array(x, delay)
    time_series_delayed = delay_array(time_series, -delay)
    plt.plot(
        x_delayed, 
        time_series_delayed, 
        label=f&#39;delay={delay}&#39;,
        alpha=1 if delay == 0 else 0.3
    )
plt.legend()

Numpy变量切片大小(可能为零)

huangapple
  • 本文由 发表于 2023年5月7日 19:30:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/76193644.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定