Having an input tensor, and another tensor selection, I want to produce the output tensor as the given below

I have the value tensor([4, 3, 6]) and index tensor([1, 1, 2])
Is there some way that I could get the result tensor([[4, 3], [6,0]]) ?

I don’t quite understand the operation you are trying to achive.
Are you looking for reshaping the tensor? or creating a tensor based on a selection from a tensor of indexes? Also, where the zero came from on the resulting tensor tensor([[4, 3], [6,0]])?

I want to create a 2-D tensor from the value tensor and index tensor, but here the index tensor is just a 1-D or is there some way to get the resulting tensor tensor([[4, 3], [6,]]) ?

I am sorry, but I am not sure if I fully understand what you want yet.
Is this what you are looking for?

input = torch.randint(10, (10, ))
input
# tensor([2, 9, 7, 9, 4, 4, 6, 1, 3, 3])

selection = torch.Tensor([0, 5, 4, 7])
selection
# tensor([0., 5., 4., 7.])

input[selection.long()].reshape((2, 2))
# tensor([[2, 4],
#        [4, 1]])

I am very sorry for my poor expression, if the value tensor is tensor([2, 9, 7, 8, 4])
the index is tensor([0, 0, 1, 2, 3])
I want to get a tensor : tensor([[2, 9], [7], [8], [4]]) or tensor([[2, 9], [7, 0], [8, 0], [4, 0]])

if there is still something that I did not let you understand, plz let me know, I will try another way to express

maybe I need to create a zero tensor
tensor([[0., 0.],
[0., 0.],
[0., 0.]])
then the index tensor tensor([0, 0, 1, 2, 3]) is the row index

You are giving

input = torch.Tensor([2, 9, 7, 8, 4])
input 
# tensor([2., 9., 7., 8., 4.])

indexes = torch.Tensor([0, 0, 1, 2, 3])
indexes
# tensor([0., 0., 1., 2., 3.])

desired = torch.Tensor([[2, 9], [7, 0], [8, 0], [4, 0]])
desired
# tensor([[2., 9.],
#         [7., 0.],
#         [8., 0.],
#         [4., 0.]])

What does it mean to have 0 inside the index tensor? Here I see you having the value 0 twice. If you are selecting elements from the given tensor, input = torch.Tensor([2., 9., 7., 8., 4.]) I would expect to see five elements been selected; and the first element, input[0] which is 2, to be repeated twice. But I don’t see that on the desired output you gave. So, I am not following what is this operation you want.

Can you describe what index does to the input tensor? How come the maximum value in index is 3, but the last element of the input tensor, which is input[4] with value 4 is present on the desired output tensor?

Additionally, as a good practice, try to be as much precise as possible which the post subject. That way, you can lead the right people to click on your post faster.

input[4] is match the indexes[4]=3, it means, put the input[4]=4 in the third raw of the desired tensor

I am very appreciate for your reply!!!

I do want get the tensor

tensor([[2., 9.],

[7., 0.],

[8., 0.],

[4., 0.]])

input = torch.Tensor([2, 9, 7, 8, 4])

The index tensor([0, 0, 1, 2, 3]) is just the raw index you can find, here I do not give the column index!
From index tensor, we can find out that\ the 0th raw has the max length 2 because 0 repeated twice in index tensor , others are just 1, so in order to fill the desired tensor, there are some 0 value in desired tensor!

I also create a new post which describes my means, may be it will let you get my thought

Ok, I understood now what you want. I can’t see an elegant way to have a solution using plain PyTorch. The “naive” way to do it would be via a for loop.

First, let me redefine what I think you are asking:


Having an input tensor, and another tensor selection, I want to produce the output tensor as the given below.

input = torch.Tensor([2, 9, 7, 8, 4])
input 
# tensor([2., 9., 7., 8., 4.])

selection = torch.Tensor([0, 0, 1, 2, 3])
selection
# tensor([0., 0., 1., 2., 3.])

desired = torch.Tensor([[2, 9], [7, 0], [8, 0], [4, 0]])
desired
# tensor([[2., 9.],
#         [7., 0.],
#         [8., 0.],
#         [4., 0.]])

Explanation

selection has same size as input and contains the row in which each input data will be mapped into. If the row index repeats, then that next raw data input will be placed into a new column. All the other rows are padded with zero on that case.


The following assumption was not stated initially. But if it holds true, the code is more straight forward. Also, the provided example allow us to infer that.

Assumption: All rows indexes are represented in selection tensor.

As I said earlier, I can’t think of a way to solve it in an elegant manner, relying in short nested PyTorch calls. From what I know, I don’t think it is possible. But a solution can be definitely done by using a for loop.

solution using for loop.

unique, counters = selection.unique(return_counts=True)
n_rows, n_cols = int(torch.max(unique))+1, int(torch.max(counters.int()))

col = np.zeros((n_rows, ), dtype=int)
output = torch.zeros((n_rows, n_cols))

for data, row in zip(input, selection.tolist()):
  output[row, col[row]] = data
  col[row] += 1
  print(col)

output
# tensor([[2., 9.],
#         [7., 0.],
#         [8., 0.],
#         [4., 0.]])

PS: I guess this operation you are looking for can also be explained as a sort of group by

I think you should be able to rename this post. So, you didn’t have to create a new one.

Also, I encourage you to enhance the format of your posts. There is a bar with text style options to assist you. That way people can read the content you wrote more comfortably.

OHHHHH!!! Thank u very very much!!!