简体   繁体   中英

Python: Plotting a Histogram Downward

I am trying to plot a histogram from a set of user input values.

Okay, I updated my code to this:

number1 = ""
number2 = ""
number3 = ""
number4 = ""

numbers = input("Enter a string of positive integers separated by spaces: ")
print(" ")
newNum = numbers.split()

line = 0
col = 0
lines = int(max(newNum))
length = len(newNum)

while line<lines:
    col = 0
    while col<length:
        if line<int(newNum[col]):
            print('* ', end = '')
        else:
            print('  ')
        col = col+1
    line = line+1
    print("")

But when I run the code I get this:

Enter a string of positive integers separated by spaces: 1 3 20 5

* * * * 

* * * 

* * * 


* * 


* * 

What am I missing now to get my histogram to print like this? Also, why is it not printing the values to 20?

Enter a string of positive integers separated by spaces: 1 3 20 5

* * * *
  * * *
  * * *
    * *
    * *
    *
    *
    *
    *
    *
    *
    *
    *
    *
    *
    *
    *
    *
    *
    *

You're going to have to program it manually.

For example, if we're at a line that is less than or below the element. This rough sample should guide you:

line = 0
col = 0
lines = max(newNum)
length = len(newNum)

return    
while line<lines:
    while col<length:
        if line<newNum[col]:
            print "* ",
        else:
            print "  ",
        col = col+1
    line = line+1
    print ""

in your example you never reset col ; you probably should set col=0 each time before starting the second while loop:

while line<lines:
    col=0
    while col<length:
        ...

otherwise the inner loop runs once only.

a nested for loop might be more natural for that...

and when printing inside a row, you want no endline character; you should use print('* ', end='') and use an empty print() at the end of every row.

then you should convert your numbers to integers as soon as possilbe:

newNum = [int(i) for i in numbers.split()]

otherwise max(newNum) will return '5' - the highest digit in the string.

and you are still missing and end=' ' in the print(' ') statement.

this should fix your issues.


a more elegant version - counting down the list of numbers until the list consists of zeroes only:

def vertical_histo(number_list):
    rest = number_list
    while any(rest):
        print(' '.join('*' if i else ' ' for i in rest))
        rest = [i-1 if i else 0 for i in rest]

# to get your example, call this function with:
vertical_histo(number_list=(1, 3, 20, 5)))

rest holds the amount of * you still need to display for each column

rest = (1, 3, 20, 5)  # first round
rest = [0, 0, 17, 2]  # after 3 rounds
# ...etc
rest = [0, 0, 1, 0]   # last round
rest = [0, 0, 0, 0]   # when done

then these are shifted down (right) by one in every iteration.

' '.join('*' if i else ' ' for i in ones)

this then creates a string with a '*' for every entry in rest that is not zero yet. otherwise it will add a ' ' .

any(rest) is True as long as ones contains non-zero entries.

Thanks to all! With this code I was able to solve the question:

number1 = ""
number2 = ""
number3 = ""
number4 = ""

numbers = input("Enter a string of positive integers separated by spaces: ")
print(" ")
newNum = [int(i) for i in numbers.split()]

line = 0
col = 0
lines = int(max(newNum))
length = len(newNum)

while line<lines:
    col = 0
    while col<length:
        if line<int(newNum[col]):
            print('* ', end = '')
        else:
            print('  ', end = '')
        col = col+1
    line = line+1
    print("")

Let's give the name data to a list containing the depth of each column in your histogram

data = [3, 5, 2]

How many rows are you going to print?

nrows = max(data) #=> 5

If you ask Python to count your rows, Python starts from 0 and stops at nrows-1

for row in range(nrows): print(row) #=> 0 1 2 3 4

So the row no. 3 has index row equal to 2 and row no. 4 has index 3 , now think of the first column of the histogram, you have to print 3 '+' , this means a '+' in row no.3 (ie, row=2 ) and nothing in row no.4 (ie, row=3 )

'+' if (data[col] > row) else ' '

After this analysis we can write the function that computes the histogram

def histogram(data):
    return '\n'.join(
        ''.join('+' if depth>row else ' ' for depth in data)
        for row in range(max(data)))

and we are ready to test it

In [36]: def histogram(data):
    ...:         return '\n'.join(
    ...:             ''.join('+' if depth>row else ' ' for depth in data)
    ...:             for row in range(max(data)))
    ...: 

In [37]: print(histogram((3,4,5,6)))
++++
++++
++++
 +++
  ++
   +

In [38]: 

Or, shorter,

In [38]: def histogram(d, nl='\n'.join, jn=''.join):
...:     return nl(jn('+'if n>r else' 'for n in d)for r in range(max(d)))
...: 

In [39]: print(histogram((3,4,5,6)))
++++
++++
++++
 +++
  ++
   +

In [40]: 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM