4

I have a dictionary band1 as shown below, I want to print out a graph based on the first and last element of each list in the dictionary. The first element of each list on the x axis, is a frequency and the last element is a reception strength and should be on the y axis. Eg, 10812 has a strength of 16 etc

band1 = {'channel1': [10564, 2112.8, 1922.8, 0],
         'channel10': [10787, 2157.4, 1967.4, 11],
         'channel11': [10812, 2162.4, 1972.4, 16],
         'channel12': [10837, 2167.4, 1977.4, 46],
         'channel2': [10589, 2117.8, 1927.8, 29],
         'channel3': [10612, 2122.4, 1932.4, 0],
         'channel4': [10637, 2127.4, 1937.4, 40],
         'channel5': [10662, 2132.4, 1942.4, 54],
         'channel6': [10687, 2137.4, 1947.4, 0],
         'channel7': [10712, 2142.4, 1952.4, 50],
         'channel8': [10737, 2147.4, 1957.4, 19],
         'channel9': [10762, 2152.4, 1962.4, 24]}

I have no problem sorting this, channel1 -> channel12 but what are some nice ways to print a pretty graph, the amount of entries in the dictionary can vary with there being more or less channels.

6
  • 1
    Have you considered using a graphing library like pyplot? It should be pretty easy to do with pyplot. Commented Apr 26, 2013 at 15:48
  • Thanks I am interested to see what libraries there are but also to see is there any nice way without downloading anything extra. This will just be printed out in console. Will have a look at pyplot now cheers. Commented Apr 26, 2013 at 15:50
  • I'm not aware of any ASCII-based graphing solutions, but you could probably put something together by hand quite easily. If the first and last elements of each list are the x and y axes respectively, how would you indicate the channel names, or does it not matter? It might help if you gave an simple example of how the resultant graph should look. Commented Apr 26, 2013 at 16:02
  • @Paul It would be very hard to graph something solely by printing. A graphing library is much more easier to use. If you don't want to download anything extra, you can always try Tkinter (the native graphics library), but it is a little harder to learn. Commented Apr 26, 2013 at 16:06
  • related: Command-line Unix ASCII-based charting / plotting tool Commented Apr 26, 2013 at 18:36

1 Answer 1

6

Here's an algorithm of point diagram, as simple and naive as it could be. Of course, its performance is far from being performed and could be optimized, as well as the output could have some axes and numbers on it.

HEIGHT = 10
WIDTH = 40
MARKER = '*'
FILL_CHARACTER = ' '

coords = [(ch[0], ch[3]) for ch in band1.values()]


# Convert to coordinates of a desired ASCII area

xmin = min(c[0] for c in coords)
xmax = max(c[0] for c in coords)
kx = (WIDTH - 1)  / (xmax - xmin)

ymin = min(c[1] for c in coords)
ymax = max(c[1] for c in coords)
ky = (HEIGHT - 1) / (ymax - ymin)

acoords = [(round((c[0] - xmin) * kx),
            round((c[1] - ymin) * ky)) for c in coords]

# Actually draw the graph

for y in range(HEIGHT, -1, -1):
    chars = []
    for x in range(WIDTH):
        if (x, y) in acoords:
            chars.append(MARKER)
        else:
            chars.append(FILL_CHARACTER)
    print(''.join(chars))

Results to:

              *                         
                     *                 *
          *                             

    *                                   
                            *           
                         *         *    
                                *       

*      *          *                     

If x coordinates are unique, it can be quite easily modified to draw column or line diagrams.

E.g. for case of bars:

HEIGHT = 10
WIDTH = 40
MARKER = '*'
FILL_CHARACTER = ' '

coords = [(ch[0], ch[3]) for ch in band1.values()]
coords.sort(key=lambda ch: ch[1])

xmin = min(c[0] for c in coords)
xmax = max(c[0] for c in coords)
kx = (WIDTH - 1)  / (xmax - xmin)

ymin = min(c[1] for c in coords)
ymax = max(c[1] for c in coords)
ky = (HEIGHT - 1) / (ymax - ymin)

acoords = {}
for c in coords:
    x = round((c[0] - xmin) * kx)
    y = round((c[1] - ymin) * ky)
    if x not in acoords:
        acoords[x] = y
    else:
        acoords[x] = max(acoords[x], y)

for y in range(HEIGHT, -1, -1):
    chars = []
    for x in range(WIDTH):
        if acoords.get(x, 0) >= y:
            chars.append(MARKER)
        else:
            chars.append(FILL_CHARACTER)
    print(''.join(chars))

Results to:

              *                         
              *      *                 *
          *   *      *                 *
          *   *      *                 *
    *     *   *      *                 *
    *     *   *      *      *          *
    *     *   *      *   *  *      *   *
    *     *   *      *   *  *   *  *   *
    *     *   *      *   *  *   *  *   *
****************************************
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.