xarray:重塑数据,拆分维度
xarray: reshape data, split dimension
我在 xarray
中有一个具有以下维度的数据集:
Dimensions: (subject: 30, session: 5, time: 45000)
Coordinates:
* subject (subject) object '110' '112' '114' '117' ...
* session (session) object 'week1' 'week2' 'week3' ...
* time (time) timedelta64[ns] 00:00:00 00:00:00.040000 ...
我想将每个试验(subject/session 组合)分成更小的时间段,例如分成 3 个段,每个段有 15000 个值,结果维度可能如下所示:
(subject: 30, session: 5, segment: 3, time: 15000)
我已经搜索并尝试了很多东西,但都没有成功,这怎么办?
我一直在尝试的其中一件事似乎很接近,那就是创建一个新的 MultiIndex 并将其取消堆叠。
segment_data = np.repeat(range(3),len(ds.time)//3)
segment = xr.Variable(dims='time',data=segment_data)
newtime_data = np.tile(ds.time[:len(ds.time)//3],3)
newtime = xr.Variable(dims='time',data=newtime_data)
dsr = ds.assign_coords(segment=segment,newtime=newtime)
dsr = dsr.set_index(segment='segment',newtime='newtime')
dsr = dsr.stack(fragment=['segment','newtime'])
然而,最后一行占用大量内存并且似乎创建了一个维度 fragment: len(ds.time)**2
,这似乎不正确。我也不确定在此之后我必须做什么 (unstack('fragment')
?)。
编辑:更多尝试让我来到这里:
x = np.repeat(range(3),15000)
y = np.tile(ds.time[:len(ds.time)//3],3)
dsr = (ds.assign_coords(segment=x,time2=y)
.set_index(fragment=['segment','time2'])
.unstack('fragment'))
这给出了这个:
(subject: 30, segment: 3, session: 5, time: 45000, time2: 15000)
这看起来很接近,但还不够,因为每个 time2
点现在都有 45000 个值,而它应该是一个值:
dsr.isel(subject=0,segment=0,session=0,time2=0)
# (time: 45000)
编辑:我终于找到了一种方法,请看我的回答。欢迎提出更多建议!
首先确保您拥有两个新维度的标签。本例如下:
x = range(3) # 3 segments
y = ds.time[:len(ds.time)//3] # the first 1/3rd of the time labels
然后根据这些标签创建一个 pandas
MultiIndex*。
ind = pd.MultiIndex.from_product((x,y),names=('segment','new_time'))
最后,用这个新索引替换数据集中的 time
索引,然后拆分其级别以创建两个所需的维度。
dsr = ds.assign(time=ind).unstack('time')
您可能想要使用 rename
重命名新维度:
dsr = dsr.rename({'new_time':'time'})
结果维度:
(subject: 30, segment: 3, session: 5, time: 15000)
现在唯一不对的是维度的顺序(理想情况下 segment
和 session
应该交换)。我认为 transpose
会有所帮助,但 "although the order of dimensions on each array will change, the dataset dimensions themselves will remain in fixed (sorted) order." ** 所以我可能会像这样忍受它。
* 请注意,您将无法使用要拆分的维度的名称,因此我们在此处使用 'new_time'
。 assign
?
的不必要限制
** 另一个我无法解释的限制。
我在 xarray
中有一个具有以下维度的数据集:
Dimensions: (subject: 30, session: 5, time: 45000)
Coordinates:
* subject (subject) object '110' '112' '114' '117' ...
* session (session) object 'week1' 'week2' 'week3' ...
* time (time) timedelta64[ns] 00:00:00 00:00:00.040000 ...
我想将每个试验(subject/session 组合)分成更小的时间段,例如分成 3 个段,每个段有 15000 个值,结果维度可能如下所示:
(subject: 30, session: 5, segment: 3, time: 15000)
我已经搜索并尝试了很多东西,但都没有成功,这怎么办?
我一直在尝试的其中一件事似乎很接近,那就是创建一个新的 MultiIndex 并将其取消堆叠。
segment_data = np.repeat(range(3),len(ds.time)//3)
segment = xr.Variable(dims='time',data=segment_data)
newtime_data = np.tile(ds.time[:len(ds.time)//3],3)
newtime = xr.Variable(dims='time',data=newtime_data)
dsr = ds.assign_coords(segment=segment,newtime=newtime)
dsr = dsr.set_index(segment='segment',newtime='newtime')
dsr = dsr.stack(fragment=['segment','newtime'])
然而,最后一行占用大量内存并且似乎创建了一个维度 fragment: len(ds.time)**2
,这似乎不正确。我也不确定在此之后我必须做什么 (unstack('fragment')
?)。
编辑:更多尝试让我来到这里:
x = np.repeat(range(3),15000)
y = np.tile(ds.time[:len(ds.time)//3],3)
dsr = (ds.assign_coords(segment=x,time2=y)
.set_index(fragment=['segment','time2'])
.unstack('fragment'))
这给出了这个:
(subject: 30, segment: 3, session: 5, time: 45000, time2: 15000)
这看起来很接近,但还不够,因为每个 time2
点现在都有 45000 个值,而它应该是一个值:
dsr.isel(subject=0,segment=0,session=0,time2=0)
# (time: 45000)
编辑:我终于找到了一种方法,请看我的回答。欢迎提出更多建议!
首先确保您拥有两个新维度的标签。本例如下:
x = range(3) # 3 segments
y = ds.time[:len(ds.time)//3] # the first 1/3rd of the time labels
然后根据这些标签创建一个 pandas
MultiIndex*。
ind = pd.MultiIndex.from_product((x,y),names=('segment','new_time'))
最后,用这个新索引替换数据集中的 time
索引,然后拆分其级别以创建两个所需的维度。
dsr = ds.assign(time=ind).unstack('time')
您可能想要使用 rename
重命名新维度:
dsr = dsr.rename({'new_time':'time'})
结果维度:
(subject: 30, segment: 3, session: 5, time: 15000)
现在唯一不对的是维度的顺序(理想情况下 segment
和 session
应该交换)。我认为 transpose
会有所帮助,但 "although the order of dimensions on each array will change, the dataset dimensions themselves will remain in fixed (sorted) order." ** 所以我可能会像这样忍受它。
* 请注意,您将无法使用要拆分的维度的名称,因此我们在此处使用 'new_time'
。 assign
?
** 另一个我无法解释的限制。