0

How can I create variables depending on how many the user wants (defined by a simple question at the start)?

import random as ran
from random import *
import matplotlib
import matplotlib.pyplot as plt

coordonei = ran.randint(0,15)
coordoneii = ran.randint(0,15)

coordtwoi = ran.randint(coordonei, coordonei + 5)
coordtwoii = ran.randint(coordoneii, coordoneii + 5)

coordthreei = ran.randint(coordtwoi, coordtwoi + 5)
coordthreeii = ran.randint(coordtwoii, coordtwoii + 5) 

print("(",coordonei,",",coordoneii,")",
"(",coordtwoi,",",coordtwoii,")",
"(",coordthreei,",",coordthreeii,")")

plt.xlim(0, 20)
plt.ylim(0, 20)
plt.xlabel("X Axis")
plt.ylabel("Y Axis")

x_values = [coordonei, coordtwoi, coordthreei]
y_values = [coordoneii, coordtwoii, coordthreeii]
plt.plot(x_values, y_values)

plt.plot(coordonei, coordoneii, '.r-')
plt.plot(coordtwoi, coordtwoii, '.r-')
plt.plot(coordthreei, coordthreeii, '.r-')

plt.show()

This simple code just produces a complete random line graph every time. I would like to be able to pick how many coordinates are in that graph.

Tim Roberts
  • 48,973
  • 4
  • 21
  • 30
kylerpal
  • 11
  • 3
  • 3
    Well, you'd read the number with `count = int(input"How many coordinates?"))`. Then you use that value to size your arrays. Right? – Tim Roberts Dec 27 '21 at 22:55

4 Answers4

2

You can use a list for them, like you where using x_values and y_values

Then you can ask the user for the coordinates like this:

number = input("How many coordinates do you want to create? ")
number = int(number)

x_values = []
y_values = []

while number:
    cor = input("Enter coordinate (x y): ")
    x, y = cor.split(" ")
    print("(" + str(x) + ", " + str(y) + ")")

    x_values.append(x)
    y_values.append(y)
    number -= 1

And finally you can rework the last part to plat the functions using a for loop:

plt.plot(x_values, y_values)

for x, y in zip(x_values, y_values):
    plt.plot(x, y, '.r-')

The complete code would look like this:

import random as ran
from random import *
import matplotlib
import matplotlib.pyplot as plt

number = input("How many coordinates do you want to create? ")
number = int(number)

x_values = []
y_values = []

while number:
    cor = input("Enter coordinate (x y): ")
    x, y = cor.split(" ")
    print("(" + str(x) + ", " + str(y) + ")")

    x_values.append(x)
    y_values.append(y)
    number -= 1

plt.xlim(0, 20)
plt.ylim(0, 20)
plt.xlabel("X Axis")
plt.ylabel("Y Axis")

plt.plot(x_values, y_values)

for x, y in zip(x_values, y_values):
    plt.plot(x, y, '.r-')

plt.show()
2

Here's a fairly clean and simple solution, doing the same you did, but a bit more pythonic:

from random import randint
import matplotlib.pyplot as plt

# n can be any number of course
n = 10

# start a list of tuples with a first tuple of coordinates (x, y)
cs = [(randint(0, 15), randint(0, 15))]
# create n-1 more of them after it
for __ in range(n - 1):
    # cs[-1] is the last tuple in the list, so cs[-1][0] is the x of that tuple
    cs.append((randint(cs[-1][0], cs[-1][0] + 5), randint(cs[-1][1], cs[-1][1] + 5)))

# these are handy for plotting, see below for nicer solution
x_values = [x for x, __ in cs]
y_values = [y for __, y in cs]


# the limits of the plot will be set to 3 beyond the maximum values
plt.xlim(0, max(x_values)+3)
plt.ylim(0, max(y_values)+3)
plt.xlabel("X Axis")
plt.ylabel("Y Axis")

plt.plot(x_values, y_values)

# add the marks
for x, y in cs:
    plt.plot(x, y, '.r-')

plt.show()

Even nicer, if you ask me:

from random import randint
import matplotlib.pyplot as plt

n = 10

cs = [(randint(0, 15), randint(0, 15))]
for __ in range(n - 1):
    # I changed this for readability, doesn't even need a comment
    cx, cy = cs[-1]
    cs.append((randint(cx, cx + 5), randint(cy, cy + 5)))

plt.xlim(0, max(x for x, __ in cs)+3)
plt.ylim(0, max(y for __, y in cs)+3)
plt.xlabel("X Axis")
plt.ylabel("Y Axis")

# this zips up all the tuples into a tuple of lists of x's and y's 
# and then unpacks that tuple 
plt.plot(*zip(*cs))

# add the marks
for x, y in cs:
    plt.plot(x, y, '.r-')

plt.show()

I think this is nicer because it avoids creating copies of your data, keeping all the coordinates in a nice and simple list of pairs (tuples) of x and y. All the operations just reference that list cs which means it could be a really long one, and your script would still work quickly and without wasting space (or introducing the opportunity to accidentally change one copy, but forgetting the other).

Ah, and to complete the answer to your question, you want to start with:

n = int(input('Any positive number:'))

If you want to see where the data ended up in your chart:

for i, (x, y) in enumerate(cs):
    plt.annotate(f'{i}:{(x, y)}', xy=(x, y), xytext=(x + 1, y - .5))
Grismar
  • 27,561
  • 4
  • 31
  • 54
  • Initial list with first coordinate as base-value is useful both as seed for populating and as default (return). The visual clarity and code symmetry of `max(x for x, __ in cs)` and its y-counterpart are beautiful to read. – hc_dev Dec 28 '21 at 01:33
1

You can store them in a list:

numVar = input('How many variables?')
numVar = int(numVar)

myVars = [ varFunc() for i in range(numVar)] #varFunc would be a function that returns random variables in your case.
    
Ryan Fu
  • 349
  • 1
  • 5
  • 22
  • 1
    I like your solution, using two idiomatic patterns: [list comprehension](https://docs.python.org/3/tutorial/datastructures.html#list-comprehensions) and [generator like `range` function](https://wiki.python.org/moin/Generators). Would love to see your example implementation for `varFunc` - even as pseudo-code. – hc_dev Dec 29 '21 at 17:23
1

The ingredients

Decomposed into 3 ingredients (functions):

  1. Read the int number of coordinates from user via input
  2. Implement a generate_random_coords(num) function that returns a list of tuples - pair of (x,y) represents a coordinate
  3. Pass the coordinates to a custom plot function

See also:

The outline

from random import randint
import matplotlib.pyplot as plt

# define the 3 ingredients (functions)

if __name__ == '__main__':
    num_coords = read_num_coords()
    coords = generate_random_coords(num_coords)
    print(coords)
    plot(coords)

The recipe

def read_num_coords():
    return int(input("Please enter number of coordinates to plot (e.g. 3):"))


def generate_random_coords(num_coords):
    coords = []
    for i in range(num_coords):
        add = 5 * (i+1)   # starts with 5, then increases by 5
        (prev_x, prev_y) = coords[i-1] if i > 0 else (0,0)  # more than previous 
        x = randint(prev_x, 10+add)
        y = randint(prev_y, 10+add)
        coords.append((x,y))
    return coords


def plot(coords):
    max_x = max([c[0] for c in coords])  # maximum of x values
    plt.xlim(0, max_x+5)  # fix min: 0, max: add 5 more
    plt.xlabel("X Axis")
    max_y = max([c[1] for c in coords])  # maximum of y values
    plt.ylim(0, max_y+5)  # fix min: 0, max: add 5 more
    plt.ylabel("Y Axis")

    plt.plot(*zip(*coords))
    plt.plot(*zip(*coords), '.r-')

    plt.show()

Bonus: Generator for coordinates

The brief but helpful answer of Ryan Fu inspires using a generator function. Like range(n) this could return an iterator to build a list of coordinates.

Following generator function can be used in an list-comprehension (like [i in range(3)]) with generator expression (like i in range(3)):

def random_coordinates(count, max_x, max_y):
        x = randint(0, max_x)
        y = randint(0, max_y)
        yield (x,y)

Use coords = [c for c in random_coordinates(num_coords, 20, 10)] as replacement for coords = generate_random_coords(num_coords) in above code recipe.

Note: Whereas previous list-factory generate_random_coords used the previous coordinate as offset for the next using a step of 5, this generator does not keep track of spacing. Instead we use the complete area from (0,0) to (max_x, max_y) to generate the coordinates randomly.

Now we explicitly predefine the maximum values for the plot's x and y axis with arguments max_x = 20 and max_y = 10.

hc_dev
  • 8,389
  • 1
  • 26
  • 38
  • Bonus questions: (1) What would be a reasonable default for num_coords? (2) Which user input can crash the plot? (3) What are (implicit) assumptions about the minimum values for (x,y)? – hc_dev Dec 28 '21 at 01:24