Format items in a list automatically - python

How would I correctly format a list of items without having to manually do it?
xy_coords = [(15, 5),
(9, 0),
(3, 5),
(13, 7),
(21, 1),
(19, 22),
(22, 2),
(11, 11),
(10, 21),
(24, 2),
(19, 19)]

First of all, the variable xy_coords is not a list. You will get an error if you run that line.
Ignoring that, and assuming xy_coords is a String, it will look like this:
xy_coords = '[(15, 5) (9, 0) (3, 5) (13, 7) (21, 1) (19, 22) (22, 2) (11, 11) (10, 21) (24, 2) (19, 19)]'
(note the single quotes above, which makes xy_coords a string)
Now, to add the commas between each tuple, you can do this:
new = ''
a = string.split(') ')
for k in a[:-1]:
new+=(k+'), ')
new+=a[-1]
print(new)
OUTPUT
[(15, 5), (9, 0), (3, 5), (13, 7), (21, 1), (19, 22), (22, 2), (11, 11), (10, 21), (24, 2), (19, 19)]

If xy_coords is a string, I would have used a RegEx to find all occurrences of couples (x, y) and then convert the strings into integers.
This can be done with the re.findall function. The RegEx can be minimal and only match the two coordinates. By using groups in your RegEx, the function will return a list of string tuples that you need to convert into int.
For instance:
import re
xy_coords = '[(15, 5) (9, 0) (3, 5) (13, 7) (21, 1) (19, 22) (22, 2) (11, 11) (10, 21) (24, 2) (19, 19)]'
xy_coords = [
tuple(map(int, coord))
for coord in re.findall(r"(\d+),\s*(\d+)", xy_coords)
]
print(xy_coords)
The result is a list of int tuples:
[(15, 5), (9, 0), (3, 5), (13, 7), (21, 1), (19, 22), (22, 2), (11, 11), (10, 21), (24, 2), (19, 19)]

Related

Generating a random number from highest count numbers in a list of tuples in Python

Let's say I have a list of tuples like so:
The second index of the tuple is a count of how many times the first index appeared in a dataset.
[(24, 11),
(12, 10), (48, 10),
(10, 9), (26, 9), (59, 9), (39, 9), (53, 9), (21, 9), (52, 9), (50, 9),
(41, 8), (33, 8), (44, 8), (46, 8), (38, 8), (20, 8), (57, 8),
(23, 7), (6, 7), (3, 7), (37, 7), (51, 7),
(34, 6), (54, 6), (36, 6), (14, 6), (17, 6), (58, 6), (15, 6), (29, 6),
(13, 5), (32, 5), (9, 5), (40, 5), (45, 5), (1, 5), (31, 5), (11, 5), (30, 5), (5, 5), (56, 5), (35, 5), (47, 5),
(2, 4), (19, 4), (42, 4), (25, 4), (43, 4), (4, 4), (18, 4), (16, 4), (49, 4), (8, 4), (22, 4), (7, 4), (27, 4),
(55, 3),
(28, 2)]
Example
(24, 11) = (number, count)
As you can see there are multiples of the same number in the second index. Is there a way you could collect the first six of the counts and put them into another list?
For example collect all the 11, 10, 9, 8, 7 counts and so on and then generate a number of six in length from that collection.
I am trying to generate a random number from the 6 most common numbers.
Update
This is how I managed to do it
def get_highest_lotto_count(data) -> list:
"""Takes all numbers from 2nd index then extracts the top 6 numbers"""
numbers = data["lotto"]
highest_count_numbers: list = [num[1] for num in numbers]
high_count_nums = list(set(highest_count_numbers))
high_count_nums.reverse()
return high_count_nums[:6]
data["lotto"] is the list provided above. I stripped all the 2nd index numbers (the counts) and converted to a set to remove duplicates.
This then gave me all the counts, I then took the first six from the reversed list.
def common_lotto_generator() -> list:
"""
This takes the top 6 numbers from get_highest_lotto_count and generates a list
from the all the numbers that have the same 2nd index.
Then generates a random 6 digit number from the list.
"""
high_count_numbers = get_highest_lotto_count(collect_duplicate_lotto_numbers())
data = collect_duplicate_lotto_numbers()
numbers = data["lotto"]
common_number_drawn: list = [
num[0] for num in numbers if num[1] in high_count_numbers
]
return random.sample(common_number_drawn, 6)
Then I called the above function to get the list of 6 numbers and the added the data again so i could get all the tuples that matched the 2nd index from the list of 6.
Your question is a bit unclear. You could try:
from heapq import nlargest
from random import choice
pairs = [(24, 11),
(12, 10), (48, 10),
...
(28, 2)
]
top_counts = set(nlargest(6, set(count for _, count in pairs)))
top_counts_numbers = [
number for number, count in pairs if count in top_counts
]
print(choice(top_counts_numbers))
The first part uses heapqs nlargest() to get the 6 largest counts: {6, 7, 8, 9, 10, 11}. As mentioned by others, that isn't exactly the counts you provide. Your wording here is a bit fuzzy. You could also use sorted() to do that. (I'm converting the result into a set because sets provide a fast lookup, which is done in the next step. But you don't need that.)
Selecting the corresponding numbers via a list comprehension:
[24, 12, 48, 10, 26, 59, 39, 53, 21, 52, 50, 41, 33, 44, 46, 38, 20, 57, 23,
6, 3, 37, 51, 34, 54, 36, 14, 17, 58, 15, 29]
Using choice() to select a random number from them.
I'm not complete sure whether the solution below answers your question. I'm puzzled because the top 6 count does not include the 7 and 8 frequency (whereas you seem to hint at this in your last comment).
The code sorts the tuples based on the second key and subsequently selects its entries at random.
#!/usr/local/bin/python3
import random
# Tuplelist
TupleList = [(24, 11),
(12, 10), (48, 10),
(10, 9), (26, 9), (59, 9), (39, 9), (53, 9), (21, 9), (52, 9), (50, 9),
(41, 8), (33, 8), (44, 8), (46, 8), (38, 8), (20, 8), (57, 8),
(23, 7), (6, 7), (3, 7), (37, 7), (51, 7),
(34, 6), (54, 6), (36, 6), (14, 6), (17, 6), (58, 6), (15, 6), (29, 6),
(13, 5), (32, 5), (9, 5), (40, 5), (45, 5), (1, 5), (31, 5), (11, 5), (30, 5), (5, 5), (56, 5), (35, 5), (47, 5),
(2, 4), (19, 4), (42, 4), (25, 4), (43, 4), (4, 4), (18, 4), (16, 4), (49, 4), (8, 4), (22, 4), (7, 4), (27, 4),
(55, 3),
(28, 2)]
# Sort tuples
TupleList.sort(key = lambda x: x[1])
# Select most frequent tuples
NumberOfMaxElements = 6
MaxElements = TupleList[-NumberOfMaxElements:]
print("Most frequent tuples:")
print(MaxElements)
# Random draws
print("Some random draws:")
NumberOfValues = 20
for iter in range(NumberOfValues):
RandomElement = random.randint(0, NumberOfMaxElements-1)
RandomDraw = MaxElements[RandomElement][0]
print(RandomDraw)

List of lists of tuples, sum element-wise

I have a list of lists of tuples. Each inner list contains 3 tuples, of 2 elements each:
[
[(3, 5), (4, 5), (4, 5)],
[(7, 13), (9, 13), (10, 13)],
[(5, 7), (6, 7), (7, 7)]
]
I need to get a single list of 3 tuples, summing all these elements "vertically", like this:
(3, 5), (4, 5), (4, 5)
+ + + + + +
(7, 13), (9, 13), (10, 13)
+ + + + + +
(5, 7), (6, 7), (7, 7)
|| || ||
[(15, 25), (19, 25), (21, 25)]
so, for example, the second tuple in the result list is given by the sums of the second tuples in the initial list
(4+9+6, 5+13+7) = (19, 25)
I'm trying with list/tuple comprehensions, but I'm getting a little lost with this.
You can use zip and sum for something a little longer, but without the heavyweight dependency on numpy if you aren't already using it.
>>> [tuple(sum(v) for v in zip(*t)) for t in zip(*x)]
[(15, 25), (19, 25), (21, 25)]
The outer zip pairs the corresponding tuples together; the inner zip pairs corresponding elements of those tuples together for addition.
You could do this pretty easily with numpy. Use sum on axis 0.
import numpy as np
l = [
[(3, 5), (4, 5), (4, 5)],
[(7, 13), (9, 13), (10, 13)],
[(5, 7), (6, 7), (7, 7)]
]
[tuple(x) for x in np.sum(l,0)]
Output
[(15, 25), (19, 25), (21, 25)]
You could do this with pure python code.
lst = [
[(3, 5), (4, 5), (4, 5)],
[(7, 13), (9, 13), (10, 13)],
[(5, 7), (6, 7), (7, 7)]
]
lst2 = []
for a in range(len(lst[0])):
l = []
for i in range(len(lst)):
l.append(lst[i][a])
lst2.append(l)
output = []
for a in lst2:
t = [0 for a in range(len(lst[0][0]))]
for i in range(len(a)):
for z in range(len(a[i])):
t[z]+= a[i][z]
output.append(tuple(t))
print(output)
if you change the list then its is works.
output
IN:
lst = [
[(3, 5), (4, 5), (4, 5)],
[(7, 13), (9, 13), (10, 13)],
[(5, 7), (6, 7), (7, 7)]
]
OUT:
[(15, 25), (19, 25), (21, 25)]
IN:
lst = [
[(3, 5,2), (4, 5,3), (4, 5,1)],
[(7, 13,1), (9, 13,3), (10, 13,3)],
[(5, 7,6), (6, 7,3), (7, 7,7)]
]
OUT:
[(15, 25, 9), (19, 25, 9), (21, 25, 11)]
data = [
[(3, 5), (4, 5), (4, 5)],
[(7, 13), (9, 13), (10, 13)],
[(5, 7), (6, 7), (7, 7)]
]
result = [tuple(sum(x) for x in zip(*t)) for t in zip(*data)]
print(result)
This is a one-liner, I don't think you can get more pythonic than this.

How would I do tuple unpacking such that the returned variables are paired based on being the nearest neighbor in a 2-D grid?

I am exploring neural network simulations between these "neurons" that you see in the figure below. The difficulty I have is connecting each neuron to its nearest neighbor. I first figured that I could do it by tuple unpacking, but it has become very complicated.
def _connect_cells(self):
for source, target in zip(self.cells, self.cells[1:] + [self.cells[0]]):
nc = h.NetCon(source.soma(0.5)._ref_v, target.syn, sec=source.soma)
nc.weight[0] = self._syn_w
nc.delay = self._syn_delay
source._ncs.append(nc)
In this example code snippet, the tuple unpacking is configured such that the i th neuron connects to i + 1 th neuron until neuron n. When it reaches neuron n, the n th neuron will connect back to the first neuron. This tuple unpacking is for a network structure resembling a ring of neurons.
However, in my case, the structure is a grid of n x n neurons. The list bellow corresponds to the neurons:
20 21 22 23 24
15 16 17 18 19
10 11 12 13 14
5 6 7 8 9
0 1 2 3 4
The above tuple unpacking would not work for this because neuron 4 is not supposed to connect to neuron 5. The list goes exclusively left to right due to how the neurons are created. The exact connection that I am trying to achieve is shown in the figure below. It is possible to do it manually (it would take a lot of code), but how can I approach it with a for loop in the same way as the example code?
Connection matrix
If I understand correctly you want each neuron in a square grid connect to each neighbouring neuron, horizontally, vertically or diagonally.
This will do the job:
def connect(side):
maxcol = side-1
maxrow = side*maxcol
neurons = list(range(side**2))
conns = []
for col in range(side):
for row in range(0, side**2, side):
if col < maxcol: #connect left
conns.append((neurons[row+col],neurons[row+col+1]))
if row > 0: #connect left up
conns.append((neurons[row+col],neurons[row+col+1-side]))
if row < maxrow: #connect left down
conns.append((neurons[row+col],neurons[row+col+1+side]))
if row < maxrow: #connect down
conns.append((neurons[row+col],neurons[row+col+side]))
return conns
connect(5)
[(0, 1), (0, 6), (0, 5), (5, 6), (5, 1), (5, 11), (5, 10), (10, 11), (10, 6), (10, 16), (10, 15), (15, 16), (15, 11), (15, 21), (15, 20), (20, 21), (20, 16), (1, 2), (1, 7), (1, 6), (6, 7), (6, 2), (6, 12), (6, 11), (11, 12), (11, 7), (11, 17), (11, 16), (16, 17), (16, 12), (16, 22), (16, 21), (21, 22), (21, 17), (2, 3), (2, 8), (2, 7), (7, 8), (7, 3), (7, 13), (7, 12), (12, 13), (12, 8), (12, 18), (12, 17), (17, 18), (17, 13), (17, 23), (17, 22), (22, 23), (22, 18), (3, 4), (3, 9), (3, 8), (8, 9), (8, 4), (8, 14), (8, 13), (13, 14), (13, 9), (13, 19), (13, 18), (18, 19), (18, 14), (18, 24), (18, 23), (23, 24), (23, 19), (4, 9), (9, 14), (14, 19), (19, 24)]

Specifying a color to a data value in a tuple and plotting into a graph in Python

I'm importing data from a .json file, where I transformed the dictionary into a list of tuples. These tuples represent the data as a timestamp and a value marked at that specified timestamp, such as this example:
participant_1 = [(1, 8), (2, 2), (3, 2), (4, 1), (5, 3), (6, 5), (7, 6), (8, 6), (9, 8), (10, 9), (11, 9), (12, 9), (13, 3), (14, 3), (15, 4), (16, 5), (17, 6), (18, 6), (19, 7), (20, 8), (21, 8), (22, 9), (23, 9), (24, 9), (25, 9), (26, 9), (27, 9)]
participant_2 = [(1, 5), (2, 5), (3, 1), (4, 3), (5, 4), (6, 5), (7, 5), (8, 7), (9, 8), (10, 9), (11, 10), (12, 10), (13, 10), (14, 10), (15, 10), (16, 10), (17, 10), (18, 0), (19, 0), (20, 0), (21, 0), (22, 0), (23, 0), (24, 0), (25, 0), (26, 0), (27, 0)]
I'll have multiple lists (of multiple participants) where the timestamp (first value of the tuple) will not change but the second (marked value) will. What I want to do is plot a graph where I can compare the marked values (therefore, the x-axis will be the time and the y-axis the marked values).
The way I want to compare the data is by horizontal bars where a different color would represent the marked value. These values range from 0 - 10. Thus, for each of these values, I would like to assign a color. In this way, there would be multiple horizontal bars, for each participant, and for each marked value, a different color (so that I can see the differences between the marked values of participants).
I do not wish for multiple bars for each participant - more like a stacked graph where the marked value would be one color, and those change according to the timestamp. In this way, I would be able to compare the marked values of the participants in a timeframe. I have an example from a paper:
Example
However, I couldn't find any way to do this yet.
Thanks.
You could convert each list to a dataframe, using the timestamp as index. The concatenation of these lists as columns to an assembling dataframe can be shown as a heatmap.
Here is some example code:
from matplotlib import pyplot as plt
import seaborn as sns
import pandas as pd
import numpy as np
participant_1 = [(1, 8), (2, 2), (3, 2), (4, 1), (5, 3), (6, 5), (7, 6), (8, 6), (9, 8), (10, 9), (11, 9), (12, 9), (13, 3), (14, 3), (15, 4), (16, 5), (17, 6), (18, 6), (19, 7), (20, 8), (21, 8), (22, 9), (23, 9), (24, 9), (25, 9), (26, 9), (27, 9)]
participant_2 = [(1, 5), (2, 5), (3, 1), (4, 3), (5, 4), (6, 5), (7, 5), (8, 7), (9, 8), (10, 9), (11, 10), (12, 10), (13, 10), (14, 10), (15, 10), (16, 10), (17, 10), (18, 0), (19, 0), (20, 0), (21, 0), (22, 0), (23, 0), (24, 0), (25, 0), (26, 0), (27, 0)]
participants = [participant_1, participant_2]
names = ['participant 1', 'participant 2']
pd.concat({name: pd.DataFrame(particip_data, columns=['timestamp', name]).set_index('timestamp')
for name, particip_data in zip(names, participants)}).reset_index()
full_df = pd.concat([pd.DataFrame(particip_data, columns=['timestamp', name]).set_index('timestamp')
for name, particip_data in zip(names, participants)],
axis=1)
fig, ax = plt.subplots(figsize=(15, 3))
cmap = plt.get_cmap('turbo', 11)
sns.heatmap(ax=ax, data=full_df.T, annot=True,
cmap='turbo', vmin=-0.5, vmax=10.5, cbar_kws={'ticks': np.arange(11), 'pad': 0.02})
ax.tick_params(labelrotation=0)
plt.tight_layout()
plt.show()

Python - list of tuples from file

I have completed some rather intensive calculations, and i was not able to save my results in pickle (recursion depth exceded), so i was forced to print all the data and save it in a text file.
Is there any easy way to now convert my list of tuples in text to well... list of tuples in python? the output looks like this:
[(10, 5), (11, 6), (12, 5), (14, 5), (103360, 7), (16, 6), (102725, 7), (17, 6), (18, 5), (19, 9), (20, 6), ...(it continues for 60MB)]
You can use ast.literal_eval():
>>> s = '[(10, 5), (11, 6), (12, 5), (14, 5)]'
>>> res = ast.literal_eval(s)
[(10, 5), (11, 6), (12, 5), (14, 5)]
>>> res[0]
(10, 5)
string = "[(10, 5), (11, 6), (12, 5), (14, 5), (103360, 7), (16, 6), (102725, 7), (17, 6), (18, 5), (19, 9), (20, 6)]" # Read it from the file however you want
values = []
for t in string[1:-1].replace("),", ");").split("; "):
values.append(tuple(map(int, t[1:-1].split(", "))))
First I remove the start and end square bracket with [1:-1], I replace ), with ); to be able to split by ; so that the it foesn't split by the commas inside the tuples as they are not preceded by a ). Inside the loop I'm using [1:-1] to remove the parenthesis this time and splitting by the commas. The map part is to convert the numeric strs into ints and I'm appending them as a tuple.

Categories

Resources