简体   繁体   中英

Generate repeated elements in a list based on elements of another list

I'm looking for a way to achieve something similar to what was asked in this question R: repeat elements of a list based on another list but in python.

Basically I have three lists of the same length:

a = [0.9935,0.1955,1.3165,0.0975,0.2995,-0.0075,1.5015,1.0055,0.4525,0.2235,1.3815,0.4195,1.3685,0.0325,0.0055,0.6175,0.0615,1.8115]
b = [4.01,5.207,-0.245,5.312,0.841,1.204,-0.413,4.398,5.309,1.149, -0.295,1.903,-0.851,1.236,1.39,3.48,-0.034,4.286]
c = [0.221, 0.423, 0.125, 0.228, 0.233, 0.235, 0.244, 0.249, 0.265, 0.265, 0.268, 0.268, 0.275, 0.299, 0.301, 0.316, 0.318, 0.329]

and I want to generate new repeated items in a and b based on the floats stored in c times 10 (rounded to the nearest integer). For example, the first element in a and b would have to be repeated 2 times because the first element in c is 0.221 and

int(round(c[0]*10.),0) = 2

So the first two elements in the new a_2 and b_2 lists would look like:

a_2 = [0.9935, 0.9935, ...]
b_2 = [4.01, 4.01, ...]

Applying this to the first three items in a and b would result in:

a_2 = [0.9935, 0.9935, 0.1955, 0.1955, 0.1955, 0.1955, 1.3165, ...]
b_2 = [4.01, 4.01, 5.207, 5.207, 5.207, 5.207, -0.245, ...]

since c[1]=0.423 and c[2]=0.125 which means the second and third items in a and b need to be repeated 4 and 1 times respectively.

Add

For the sake of completeness I'll mention that this question is related to the answer given in this other question How to obtain a weighted gaussian filter . So this is an integral part of what makes the answer to that other question work.

You would use zip() to combine a and c , and b and c , together with itertools.chain.from_iterable() to generate new sequences:

from itertools import chain

a_2 = list(chain.from_iterable([i] * int(round(j * 10)) for i, j in zip(a, c)))
b_2 = list(chain.from_iterable([i] * int(round(j * 10)) for i, j in zip(b, c)))

Demo:

>>> from itertools import chain
>>> a = [0.9935,0.1955,1.3165,0.0975,0.2995,-0.0075,1.5015,1.0055,0.4525,0.2235,1.3815,0.4195,1.3685,0.0325,0.0055,0.6175,0.0615,1.8115]
>>> b = [4.01,5.207,-0.245,5.312,0.841,1.204,-0.413,4.398,5.309,1.149, -0.295,1.903,-0.851,1.236,1.39,3.48,-0.034,4.286]
>>> c = [0.221, 0.423, 0.125, 0.228, 0.233, 0.235, 0.244, 0.249, 0.265, 0.265, 0.268, 0.268, 0.275, 0.299, 0.301, 0.316, 0.318, 0.329]
>>> list(chain.from_iterable([i] * int(round(j * 10)) for i, j in zip(a, c)))
[0.9935, 0.9935, 0.1955, 0.1955, 0.1955, 0.1955, 1.3165, 0.0975, 0.0975, 0.2995, 0.2995, -0.0075, -0.0075, 1.5015, 1.5015, 1.0055, 1.0055, 0.4525, 0.4525, 0.4525, 0.2235, 0.2235, 0.2235, 1.3815, 1.3815, 1.3815, 0.4195, 0.4195, 0.4195, 1.3685, 1.3685, 1.3685, 0.0325, 0.0325, 0.0325, 0.0055, 0.0055, 0.0055, 0.6175, 0.6175, 0.6175, 0.0615, 0.0615, 0.0615, 1.8115, 1.8115, 1.8115]
>>> list(chain.from_iterable([i] * int(round(j * 10)) for i, j in zip(b, c)))
[4.01, 4.01, 5.207, 5.207, 5.207, 5.207, -0.245, 5.312, 5.312, 0.841, 0.841, 1.204, 1.204, -0.413, -0.413, 4.398, 4.398, 5.309, 5.309, 5.309, 1.149, 1.149, 1.149, -0.295, -0.295, -0.295, 1.903, 1.903, 1.903, -0.851, -0.851, -0.851, 1.236, 1.236, 1.236, 1.39, 1.39, 1.39, 3.48, 3.48, 3.48, -0.034, -0.034, -0.034, 4.286, 4.286, 4.286]

If a , b and c are particularly large, or if for certain values of c times 10 lead to a lot of repetitions and you only need to process these values one by one (eg you don't need to materialize the whole a_2 and b_2 lists in memory), you could use more itertools functions here:

from itertools import chain, repeat, izip

a_2_generator = chain.from_iterable(repeat(i, int(round(j * 10))) for i, j in izip(a, c))
b_2_generator = chain.from_iterable(repeat(i, int(round(j * 10))) for i, j in izip(b, c))

Note the lack of list() here; now each stage is handled by iterators producing only enough to satisfy one step at a time, saving on memory.

Use this if you need if you only need to iterate over the output once; if your plot library takes a general iterable for plotting these should work just fine.

You can use chain , izip and repeat :

from itertools import chain, repeat, izip
new_a = list(chain.from_iterable(repeat(el, int(round(n * 10))) for el, n in izip(a, c)))

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