Create array from randomly extracted data from array of arrays - python

Suppose that I have the following array or arrays:
[[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],[0, 1, 2, 3, 4, 5],[0, 1, 2, 3, 4, 5, 6, 7]]
What's the best way to loop into the main array and randomly extract one number from each sub-array every time and create another array with them? For instance, in the first pass, the result would be:
[2,5,6]
The second pass could be:
[8,0,7]
etc. At this stage I don't have any clues how to do it.

If you have python lists, you can use random.choice in a list comprehension:
L = [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],[0, 1, 2, 3, 4, 5],[0, 1, 2, 3, 4, 5, 6, 7]]
from random import choice
out = [choice(l) for l in L]
example output:
[3, 0, 5]
variant
Imagine you want to pick each item only a single time in each iteration, you could also use pop on a random position:
L = [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],[0, 1, 2, 3, 4, 5],[0, 1, 2, 3, 4, 5, 6, 7]]
for i in range(6):
print([l.pop(np.random.randint(len(l))) for l in L])
Obviously, here you cannot have a number of iterations greater than the length of the shortest sublist
example output:
[5, 4, 0]
[2, 2, 6]
[3, 5, 7]
[0, 1, 1]
[4, 3, 2]
[9, 0, 3]

Related

Filter a Python list using Dictionary keys and values

GOAL: Filter a list of lists using dictionary as reference in Python 3.8+
CASE USE: When reviewing a nested list -- a series of survey responses -- filtering out responses based on control questions. In the dictionary, the responses to questions 3 (index 2 in list) and 7 (index 6) should both be of corresponding value 5. If both answers for a response are not 5, they should not be populated in the filtered_responses list.
Open to interpretation on how to solve for this. I have reviewed several resources touching on filtering dictionaries using lists. This method is preferred as some survey responses many contain the same array of values, therefore the list element is retained.
no_of_survey_questions = 10
no_of_participants = 5
min_score = 1
max_score = 10
control_questions = {3: 5,
7: 5, }
unfiltered_responses = [[4, 5, 4, 5, 4, 5, 4, 5, 4, 5], # omit
[9, 8, 7, 6, 5, 4, 3, 2, 1, 1], # omit
[5, 5, 5, 5, 5, 5, 5, 5, 5, 5], # include
[5, 2, 5, 2, 5, 2, 5, 9, 1, 1], # include
[1, 2, 5, 1, 2, 1, 2, 1, 2, 1]] # omit
for response in unfiltered_responses:
print(response)
print()
filtered_responses = [] # should contain only unfiltered_responses values marked 'include'
for response in filtered_responses:
# INSERT CODE HERE
print(response)
Thanks in advance!
You can use list comprehension + all():
control_questions = {3: 5,
7: 5}
unfiltered_responses = [[4, 5, 4, 5, 4, 5, 4, 5, 4, 5], # omit
[9, 8, 7, 6, 5, 4, 3, 2, 1, 1], # omit
[5, 5, 5, 5, 5, 5, 5, 5, 5, 5], # include
[5, 2, 5, 2, 5, 2, 5, 9, 1, 1], # include
[1, 2, 5, 1, 2, 1, 2, 1, 2, 1]] # omit
filted_questions = [subl for subl in unfiltered_responses if all(subl[k-1] == v for k, v in control_questions.items())]
print(filted_questions)
Prints:
[
[5, 5, 5, 5, 5, 5, 5, 5, 5, 5],
[5, 2, 5, 2, 5, 2, 5, 9, 1, 1]
]

Python - trying to unpack a list comprehension to understand it

This is a basic question that I am trying to figure out but can't seem to. I have a list comprehension that works as expected (for Advent of Code). For my reference I am trying to unpack it.
raw_data = """
30373
25512
65332
33549
35390
"""
forest = [[int(x) for x in row] for row in raw_data.split()]
print(forest)
which outputs:
[[3, 0, 3, 7, 3], [2, 5, 5, 1, 2], [6, 5, 3, 3, 2], [3, 3, 5, 4, 9], [3, 5, 3, 9, 0]]
So I am trying to unpack it to better understand it but it's not working as I expect.
t = []
for row in raw_data.split():
for x in row:
t.append(int(x))
print(t)
which outputs:
[3, 0, 3, 7, 3, 2, 5, 5, 1, 2, 6, 5, 3, 3, 2, 3, 3, 5, 4, 9, 3, 5, 3, 9, 0]
I think this is what you're looking for:
t = []
for row in raw_data.split():
r = []
for x in row:
r.append(int(x))
t.append(r)
print(t)

Insert an element in a list into kth position each sublist (from left to right after inserting k+=1) of another list- Python

There are 3 subsets in Spi, each subset contains its sublists and I denoted it as Spi[d][l] (d is the number of subsets and l is the number of sublists).
I want to enter each subset to insert just one specific number which is an element of S_inter into the 3rd, 4th, and 5th (3, 4, 5 are elements of in_inter_job) position of each sublist respectively.
To be more clear, that is inserting number 4 into the first subset, next is number 2 entering to the second subset (2 will be inserted into position 3 of the first sublist, position 4 in the second sublist and 5th position in the last sublist), the do the same for number 6 and the last subset.
S_inter=[4, 2, 6]
in_inter_job=[ 3, 4, 5]
Spi=[[[1, 3, 5, 2, 6], [1, 3, 5, 2, 6], [1, 3, 5, 2, 6]], [[1, 3, 5, 4, 6], [1, 3, 5, 4, 6], [1, 3, 5, 4, 6]], [[1, 3, 5, 4, 2], [1, 3, 5, 4, 2], [1, 3, 5, 4, 2]]]
The result I wanted is like :
Spi=[[[1, 3, 5, 4, 2, 6], [1, 3, 5, 2, 4, 6], [1, 3, 5, 2, 6, 4]], [[1, 3, 5, 2, 4, 6], [1, 3, 5, 4, 2, 6], [1, 3, 5, 4, 6, 2]], [[1, 3, 5, 6, 4, 2], [1, 3, 5, 4, 6, 2], [1, 3, 5, 4, 2, 6]]]
But after I run these for loop:
for d in range(0,len(Spi)):
for k in S_inter:
for l, r in zip(range(len(Spi[d])),in_inter_job):
Spi[d][l].insert(r,k)
if len(Spi[d][l]) == 6:
break
print(" After insert ",Spi)
then I get result:
Spi=[[[1, 3, 5, 6, 6, 6, 2, 2, 2, 4, 2, 6], [1, 3, 5, 6, 6, 6, 2, 2, 2, 4, 2, 6], [1, 3, 5, 6, 6, 6, 2, 2, 2, 4, 2, 6]], [[1, 3, 5, 6, 6, 6, 2, 2, 2, 4, 4, 6], [1, 3, 5, 6, 6, 6, 2, 2, 2, 4, 4, 6], [1, 3, 5, 6, 6, 6, 2, 2, 2, 4, 4, 6]], [[1, 3, 5, 6, 6, 6, 2, 2, 2, 4, 4, 2], [1, 3, 5, 6, 6, 6, 2, 2, 2, 4, 4, 2], [1, 3, 5, 6, 6, 6, 2, 2, 2, 4, 4, 2]]]
Please help me!
Simple nested for loop to insert into each list in Spi at corresponding position in in_inter_job with corresponding value in S_inter:
S_inter=[4, 2, 6]
in_inter_job=[ 3, 4, 5]
Spi=[[[1, 3, 5, 2, 6], [1, 3, 5, 2, 6], [1, 3, 5, 2, 6]], [[1, 3, 5, 4, 6], [1, 3, 5, 4, 6], [1, 3, 5, 4, 6]], [[1, 3, 5, 4, 2], [1, 3, 5, 4, 2], [1, 3, 5, 4, 2]]]
for i, x in enumerate(S_inter):
for j, L in enumerate(Spi[i]):
pos = in_inter_job[j]
L.insert(pos, x)
print(Spi)
Your zip (which is similar to what enumerate above is doing) doesn't work, because it doesn't match your logic. The positions of in_inter_job do not directly correspond with the indexes in S_inter, and so you end up inserting the wrong values, because you're trying to use the same index for both lists.

Reorder array in Python based on a column

I have an array like this:
a = [[ 8, 7, 6, 5, 9],
[1, 2, 1, 6, 4],
[4, 2, 5, 4, 2]]`
I want to change the order of that array based on second row with an order like this:
b = [2, 6, 1, 1, 4]
So, I want the result becomes like this:
a = [[7, 5, 8, 6, 9],
[2, 6, 1, 1, 4],
[2, 4, 4, 5, 2]]
How can I solve this problem in Python?
a = [[ 8, 7, 6, 5, 9],
[1, 2, 1, 6, 4],
[4, 2, 5, 4, 2]]
a[1] = [2, 6, 1, 1, 4]
Try that.
In this answer, I'm making the following two assumptions:
All sub-lists are 5 elements in length
The desired logic is to move the 2nd and 4th elements to be 1st and 2nd respectively
If both of the assumptions made above are true, you can use list comprehension on a nested list, and create a list to specify how the lists should be reordered.
a = [[8, 7, 6, 5, 9],
[1, 2, 1, 6, 4],
[4, 2, 5, 4, 2]]
new_ord = [1, 3, 0, 2, 4]
b = [[l[i] for i in new_ord] for l in a]
print(b) #prints: [[7, 5, 8, 6, 9], [2, 6, 1, 1, 4], [2, 4, 4, 5, 2]]

Why do all the lists in my array change when I append a new list?

I'm coding with python 3.6 and am working on a Genetic Algorithm. When generating a new population, when I append the new values to the array all the values in the array are changed to the new value. Is there something wrong with my functions?
Code:
from fuzzywuzzy import fuzz
import numpy as np
import random
import time
def mutate(parent):
x = random.randint(0,len(parent)-1)
parent[x] = random.randint(0,9)
print(parent)
return parent
def gen(cur_gen, pop_size, fittest):
if cur_gen == 1:
population = []
for _ in range(pop_size):
add_to = []
for _ in range(6):
add_to.append(random.randint(0,9))
population.append(add_to)
return population
else:
population = []
for _ in range(pop_size):
print('\n')
population.append(mutate(fittest))
print(population)
return population
def get_fittest(population):
fitness = []
for x in population:
fitness.append(fuzz.ratio(x, [9,9,9,9,9,9]))
fittest = fitness.index(max(fitness))
fittest_fitness = fitness[fittest]
fittest = population[fittest]
return fittest, fittest_fitness
done = False
generation = 1
population = gen(generation, 10, [0,0,0,0,0,0])
print(population)
while not done:
generation += 1
time.sleep(0.5)
print('Current Generation: ',generation)
print('Fittest: ',get_fittest(population))
if get_fittest(population)[1] == 100:
done = True
population = gen(generation, 10, get_fittest(population)[0])
print('Population: ',population)
Output:
Fittest: ([7, 4, 2, 7, 8, 9], 72)
[3, 4, 2, 7, 8, 9]
[[3, 4, 2, 7, 8, 9]]
[3, 4, 2, 7, 5, 9]
[[3, 4, 2, 7, 5, 9], [3, 4, 2, 7, 5, 9]]
[3, 4, 2, 7, 4, 9]
[[3, 4, 2, 7, 4, 9], [3, 4, 2, 7, 4, 9], [3, 4, 2, 7, 4, 9]]
[3, 1, 2, 7, 4, 9]
[[3, 1, 2, 7, 4, 9], [3, 1, 2, 7, 4, 9], [3, 1, 2, 7, 4, 9], [3, 1, 2, 7, 4, 9]]
[3, 1, 2, 7, 4, 2]
[[3, 1, 2, 7, 4, 2], [3, 1, 2, 7, 4, 2], [3, 1, 2, 7, 4, 2], [3, 1, 2, 7, 4, 2], [3, 1, 2, 7, 4, 2]]
[3, 1, 2, 5, 4, 2]
[[3, 1, 2, 5, 4, 2], [3, 1, 2, 5, 4, 2], [3, 1, 2, 5, 4, 2], [3, 1, 2, 5, 4, 2], [3, 1, 2, 5, 4, 2], [3, 1, 2, 5, 4, 2]]
[3, 1, 2, 5, 4, 2]
[[3, 1, 2, 5, 4, 2], [3, 1, 2, 5, 4, 2], [3, 1, 2, 5, 4, 2], [3, 1, 2, 5, 4, 2], [3, 1, 2, 5, 4, 2], [3, 1, 2, 5, 4, 2], [3, 1, 2, 5, 4, 2]]
[3, 1, 2, 5, 4, 5]
[[3, 1, 2, 5, 4, 5], [3, 1, 2, 5, 4, 5], [3, 1, 2, 5, 4, 5], [3, 1, 2, 5, 4, 5], [3, 1, 2, 5, 4, 5], [3, 1, 2, 5, 4, 5], [3, 1, 2, 5, 4, 5], [3, 1, 2, 5, 4, 5]]
[3, 1, 2, 5, 4, 3]
[[3, 1, 2, 5, 4, 3], [3, 1, 2, 5, 4, 3], [3, 1, 2, 5, 4, 3], [3, 1, 2, 5, 4, 3], [3, 1, 2, 5, 4, 3], [3, 1, 2, 5, 4, 3], [3, 1, 2, 5, 4, 3], [3, 1, 2, 5, 4, 3], [3, 1, 2, 5, 4, 3]]
You keep passing fittest, a reference to the same list, to mutate, which modifies the list in-place, and append it to population, so changes to the list in the next iteration are reflected across all the references to fittest in the population list.
You should pass a copy of the fittest list to mutate instead:
population.append(mutate(fittest[:]))
It's right there in the name:
def mutate(parent):
x = random.randint(0,len(parent)-1)
parent[x] = random.randint(0,9)
print(parent)
return parent
mutate isn't making a new list, it's modifying the existing list in place and returning a reference to the same list it was passed. population.append(mutate(fittest)) is happily storing aliases to fittest over and over, and since fittest is never replaced, it just keeps getting mutated and new aliases to it stored.
If the goal is to store a snapshot of the list at a given stage each time, copy it, changing:
population.append(mutate(fittest))
to:
population.append(mutate(fittest)[:])
where a complete slice of the list makes a shallow copy. population.append(mutate(fittest).copy()) would also work on modern Python, as would import copy, then doing population.append(copy.copy(mutate(fittest))) or (if the contents might themselves be mutable, though they aren't in this case) population.append(copy.deepcopy(mutate(fittest))).
Note that as a rule, Python functions aren't really supposed to both mutate and return the mutated value, as it leads to confusion like this.
Pythonic code intended to mutate in place returns None (implicitly usually, by not returning at all), so the code you'd use would actually be:
def mutate(parent):
x = random.randint(0,len(parent)-1)
parent[x] = random.randint(0,9)
print(parent)
and used with:
mutate(fittest) # Mutate fittest in place
population.append(fittest[:]) # Append copy of most recently updated fittest

Categories