0

I have "n" numbers, I have to create a dictionary (which n will be its length and width will be i/n) to form a dictionary.

Let´s say that I have "n"=4

  y  0.25  0.5  0.75                 
0.25
0.5
0.75

# code 
data = {"y/x": []}
for i in range(n):
    data["y/x"].append(i/n)
    data[i/n] = []

Once generated the dictionary I have a list (which will always be even), you have to generate up to N/2 pairs.

List given
nums = [0.60365, 0.83799, 0.32960, 0.19322, 0.11220,
        0.37751, 0.88492, 0.30934, 0.22888, 0.78212]

Coordinates

coord = [(0.60365, 0.83799), (0.3296, 0.19322), (0.1122, 0.37751), (0.88492, 0.30934), (0.22888, 0.78212)]

#code
coord = [((nums[i]), (nums[i+1]) % len(nums))
         for i in range(0, len(nums), 2) if i < len(nums)-1]
print(coord)

How can I place the number of pairs that are within the dictionary intervals? In such a way that it looks like this?**

    y/x      0 ->0.25   .25 -> .5   .5 -> .75   .75 -> 1
 0  -> 0.25     1            1          0            0
.25 -> .5       1            2          0            1
.5  -> .75      0            0          0            1
.75 -> 1        0            1          1            0
Axel
  • 135
  • 1
  • 7
  • You want to just print it that way, or create such a data structure? Either way, this post might help. https://stackoverflow.com/questions/9535954/printing-lists-as-tabular-data (look beyond the 1st answer, 2nd and 3rd seem great) – druskacik Nov 18 '19 at 01:24
  • Thanks!, I'd like to print it as a data structure. – Axel Nov 18 '19 at 01:34

2 Answers2

0

Firstly you would build the dictionary that has as many elements as the ranges that you have in your task. Secondly, we would define a new list that would hold the range value boundaries for your dictionary. The index of each list element is equal to the appropriate coordinate in the dictionary.

This way we have clear and simple to follow keys in the dictionary and a list or values decoding the dictionary keys.

n = 4

dict = {}
for i in range(1, n+1):
  dict[i/n] = {}
  for j in range(1, n+1):
    dict[i/n][j/n] = 0
print(dict)

and the print:

[0.25, 0.5, 0.75, 1.0]
{0: {0: 0, 1: 0, 2: 0, 3: 0}, 1: {0: 0, 1: 0, 2: 0, 3: 0}, 2: {0: 0, 1: 0, 2: 0, 3: 0}, 3: {0: 0, 1: 0, 2: 0, 3: 0}}

Next you would go through your input list and mark the coordinates. The logic for that is that you need to put the 1 in the dictionary under the dictionary key that is represented by the first element in the range array that satisfy the following condition prev_range_element < value <= current_range_element.

When we know what we have to do, let's transform the initial list into a list of tupples. My approach to do it is definitely not the best, but it will have to suit this answer.

# turn the list into a set of coordinates
zipped_nums = [v for k,v in enumerate(zip(nums, nums[1:])) if k % 2 == 0 ]
print(zipped_nums)

that results in

[(0.60365, 0.83799), (0.3296, 0.19322), (0.1122, 0.37751), (0.88492, 0.30934), (0.22888, 0.78212)]

Finally we run a loop that checks the condition we defined above. I opted for a simple n^2 solution here, feel free to optimize:)

for num in zipped_nums:
  x = y = prev_range = 0
  for idx, range in enumerate(ranges):
    if num[0] <= range and num[0] > prev_range:
      x = idx
    if num[1] <= range and num[1] > prev_range:
      y = idx
    prev_range = range
  print(''+str(x) + ' ' + str(y))
  dict[x][y] += 1

That finally results in

{0: {0: 0, 1: 1, 2: 0, 3: 1}, 1: {0: 1, 1: 0, 2: 0, 3: 0}, 2: {0: 0, 1: 0, 2: 0, 3: 1}, 3: {0: 0, 1: 1, 2: 0, 3: 0}}

All you have to do now is to render the result in a nice looking table, but that is a story for another time.

Cheers~

Simas Joneliunas
  • 2,890
  • 20
  • 28
  • 35
0

I used pandas (one of the most used python libraries), as recommended in question I mentioned in the comment. I did not use your dict at all.

import pandas as pd

n = 4

nums = [0.60365, 0.83799, 0.32960, 0.19322, 0.11220,
        0.37751, 0.88492, 0.30934, 0.22888, 0.78212]

coord = [((nums[i]), (nums[i+1]) % len(nums))
         for i in range(0, len(nums), 2) if i < len(nums)-1]

# my code
borders = [0.25*i for i in range(n + 1)]
borders_as_string = list(str(borders[i]) + ' --> ' + str(borders[i + 1]) for i in range(len(borders) - 1))

values = [[0 for i in range(n)] for j in range(n)]

for c in coord:
    x = int(c[0]//0.25)
    y = int(c[1]//0.25)
    values[x][y] += 1

dataframe = pd.DataFrame(values, borders_as_string, borders_as_string)

print(dataframe)

The result will be:

              0.0 --> 0.25  0.25 --> 0.5  0.5 --> 0.75  0.75 --> 1.0
0.0 --> 0.25             0             1             0             1
0.25 --> 0.5             1             0             0             0
0.5 --> 0.75             0             0             0             1
0.75 --> 1.0             0             1             0             0

This will scale to any number of nums, for example, you can try:

import numpy as np
nums = np.random.rand(100)
druskacik
  • 2,176
  • 2
  • 13
  • 26
  • But the columns and rows will be "i/n", if I have n = 6, the ranks will be: [(0.0 -1.666), (1.666 -0.333),.............,(5/6 - 6/6)]. I tried to do that in your code but it gave me a wrong result, anyway I'll be trying, thank you very much.!! – Axel Nov 18 '19 at 02:09
  • Just change 0.25 to (1/n). – druskacik Nov 18 '19 at 02:53