Python calculating percentages from list

Question:

Hello i have a list that has the following information that is retrieved from a db

test_list_1 = ['01/01/2022:79.86','02/01/2022:65.86','03/01/2022:600.23','04/01/2022:179.26']
test_list_2 = ['01/01/2022:55.86','02/01/2022:25.75','03/01/2022:300.23']

I would like to be able to produce the following output from that:

# Output of test_list_1
01/01/2022 (79.86) => 02/01/2022 (65.86) => Percentage Diff (-17%)
01/01/2022 (79.86) => 03/01/2022 (600.23) => Percentage Diff (+651%)
01/01/2022 (79.86) => 04/01/2022 (179.26) => Percentage Diff (+124%)
02/01/2022 (65.86) => 03/01/2022 (600.23) => Percentage Diff (+811%)
02/01/2022 (65.86) => 04/01/2022 (179.26) => Percentage Diff (+172%)
03/01/2022 (600.23) => 04/01/2022 (179.26) => Percentage Diff (-70%)

# Output of test_list_2
01/01/2022 (55.86) => 02/01/2022 (25.75) => Percentage Diff (-53%)
01/01/2022 (55.86) => 03/01/2022 (300.23) => Percentage Diff (+437%)
02/01/2022 (25.75) => 03/01/2022 (300.23) => Percentage Diff (+1065%)

I am having a lot of trouble even trying to figure out the logic on how to do this. If some one can please assist me with just getting started with this that would be amazing.

Thank you very much in advance.

Asked By: Boston Whaler

||

Answers:

A solution that relies on the powerful itertools module to first generate combinations.

Applied here on test_list1.

Just make a function of that to apply to any list in argument.

from itertools import combinations

def pdiff(src: float, dst: float) -> float:
    return (dst-src)/src*100

combs = [(x,y) for x,y in combinations(test_list_1, 2)]
for x, y in combs:
    dtx, percentx = x.split(":")
    dty, percenty = y.split(":")
    print(f"{dtx} ({percentx}) => {dty} ({percenty}) => Percentage Diff ({pdiff(float(percentx), float(percenty)): .2f}%)")
Answered By: 0x0fba

You can obtain the desired output through a relatively simple set of lists manipulations. Here is my solution for the first list (it is exactly the same for the second).

test_list_1 =['01/01/2022:79.86','02/01/2022:65.86','03/01/2022:600.23','04/01/2022:179.26']

test_list_1 = [el.split(':') for el in test_list_1]

for index, value in enumerate(test_list_1):
  for next_index, next_value in enumerate(test_list_1[index+1:]):
    v = 100*(float(next_value[1]) - float(value[1]))/float(value[1])
    print(f"{value[0]} ({value[1]}) => {next_value[0]} ({next_value[1]}) => Percentage Diff ({int(v)})%")

Here I am assuming the list elements are strings and you are interested only in printing the output as you reported it.

Hope this helps, bless!

Answered By: riccardo.lobianco

You have two major hurdles to get from the starting point to the paired off values you need:

  1. Parsing the strings to useful data
  2. Matching up the parsed data to perform your computations

Parsing is fairly simple:

parsed_list_1 = []
for s in test_list_1:
    date, sep, price = s.partition(':')
    # Optionally test "if sep:" and raise an error if the data didn't have the expected colon in it
    parsed_list_1.append((date, float(price))  # Store a tuple of the date string and parsed prices

Once you’ve got a parsed list of date-price tuples, since your data is already in sorted order, you can use itertools.combinations (with import itertools at the top of the file) to pair up each date’s data with each subsequent date, e.g.:

for (start_date, start_price), (end_date, end_price) in itertools.combinations(parsed_list_1, 2):
    # Do stuff with each pair of dates and associated prices

Try it online!

I’m leaving it up to you how to compute the percentage difference, adapt the code to work with multiple input lists without writing the same code twice, format your output, and (if necessary) how to handle sorting the data if it’s not guaranteed to be in order by date already, but this is 80% of the work. You could solve it without itertools.combinations with carefully constructed nested for loops, e.g.

for i, (start_date, start_price) in enumerate(parsed_list_1, 1):
    for end_date, end_price in parsed_list_1[i:]:
        # Do stuff with each pair of dates and associated prices

but it’s slower, more verbose, and frankly less clear. The itertools module is friggin’ magic; use it when you can.

Answered By: ShadowRanger

Different solution:

lst = ['01/01/2022:79.86','02/01/2022:65.86','03/01/2022:600.23','04/01/2022:179.26']


def pairings(pool):
    for i, m in enumerate(pool):
        for n in pool[i+1:]:
            yield (m, n)

new_list = list(pairings(lst))

for i,j in new_list:
    diff = int((float(j.split(":", 1)[1]) - float(i.split(":", 1)[1]))/float(i.split(":", 1)[1])*100)
    print(i + " => " + j + " => Percentage Diff " + str(diff) + "%")
Answered By: HeadinCloud
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.