3

To plot a waterfall, I create three lists as input: the value, the bar text, the axis text. My goal is to sort every number in between the first and last element ascending, i.e. exclude the first and last element in the list from being sorted.

I have three lists containing following elements:

A = [50000,8000,-3000,-4000,51000]
B = ['Start','Profit1','Cost2','Cost1','End']
C = ['50K','8k','-3k','-4k','51k']

Using the suggested method here (sort values in list by other list), I state:

a_new = sorted(A)
b_new = [x for _, x in sorted(zip(A, B))]
c_new = [x for _, x in sorted(zip(A, C))]
print(a_new)
print(b_new)
print(c_new)

And receive as Output:

[-4000, -3000, 8000, 50000, 51000]
['Cost1', 'Cost2', 'Profit1', 'Start', 'End']
['-4k', '-3k', '8k', '50K', '51k']

Though, my goal is to fix the first and the last element of the list and sort all other elements only. Desired:

[50000,-4000,-3000,8000,51000]
['Start','Cost1', 'Cost2', 'Profit1','End']
['50K','-4k', '-3k', '8k','51k']

I think I am close to the solution, but have been stuck here for quite some time...

Botan
  • 183
  • 1
  • 11

3 Answers3

2

You can use np.argsort on the portion you want:

order = np.r_[0,np.argsort(A[1:-1]) + 1, len(A)-1]
a_new = np.array(A)[order]
b_new = np.array(B)[order]
c_new = np.array(C)[order]

Output:

[50000 -4000 -3000  8000 51000]
['Start' 'Cost1' 'Cost2' 'Profit1' 'End']
['50K' '-4k' '-3k' '8k' '51k']
Quang Hoang
  • 146,074
  • 10
  • 56
  • 74
1

Not so elegant, but i hope this solves the problem:

A = [50000,8000,-3000,-4000,51000]
B = ['Start','Profit1','Cost2','Cost1','End']
C = ['50K','8k','-3k','-4k','51k']

a_new = sorted(A[1:len(A)-1])
a_new.insert(0, A[0])
a_new.append(A[len(A)-1])
b_new = [x for _, x in sorted(zip(A[1:len(A)-1], B[1:len(A)-1]))]
c_new = [x for _, x in sorted(zip(A[1:len(A)-1], C[1:len(A)-1]))]
b_new.insert(0, B[0])
b_new.append(B[len(B)-1])
c_new.insert(0, C[0])
c_new.append(C[len(C)-1])
print(a_new)
print(b_new)
print(c_new)
Seyi Daniel
  • 2,259
  • 2
  • 8
  • 18
1

One ugly but possible way would to use list indexing:

a_new = [A[0]] + sorted(A[1:-1]) + [A[-1]]
b_new = [B[0]] + [x for _, x in sorted(zip(A[1:-1], B[1:-1]))] + [B[-1]
c_new = [C[0]] + [x for _, x in sorted(zip(A[1:-1], C[1:-1]))] + [C[-1]]

For descending:

a_new = [A[0]] + sorted(A[1:-1], reverse=True) + [A[-1]]
b_new = [B[0]] + [x for _, x in sorted(zip(A[1:-1], B[1:-1]),reverse=True)] + [B[-1]
c_new = [C[0]] + [x for _, x in sorted(zip(A[1:-1], C[1:-1]),reverse=True)] + [C[-1]]

Output for ascending:

[50000, -4000, -3000, 8000, 51000]
['Start', 'Cost1', 'Cost2', 'Profit1', 'End']
['50K', '-4k', '-3k', '8k', '51k']
Grayrigel
  • 3,474
  • 5
  • 14
  • 32