Как сжать каждый элемент из одномерного массива с элементами из каждой строки двумерного массива? - PullRequest
0 голосов
/ 14 февраля 2020

Я пытаюсь построить набор данных, используя matplotlib, который содержит несколько y координат на x. Чтобы построить их, я должен объединить эти массивы, чтобы показать их на одном графике. Как мне сжать каждый элемент из 1D массива с элементами из каждой строки 2D массива (в соответствии с индексом для элемента 1D массива)? Без использования явных циклов for. Используя встроенные модули (например, понимание zip / list) или даже лучше: numpy?

Превращение:

x = [1, 2, 3]
y = [[4, 5], [6, 7], [8, 9]]

В:

r = [(1, 4), (1, 5), (2, 6), (2, 7), (3, 8), (3, 9)]

Ответы [ 5 ]

2 голосов
/ 14 февраля 2020

Я подумал о следующем:

  1. Расширить x до размера, равного y

  2. Свести y

  3. Zip x и y

следующим образом

>>> x = [1, 2, 3]
>>> y = [[4, 5], [6, 7], [8, 9]]
>>> x = np.array(x).repeat(2)
>>> y = np.array(y).reshape(-1)
>>> list(zip(x, y))
[(1, 4), (1, 5), (2, 6), (2, 7), (3, 8), (3, 9)]

Я хотел бы узнать, как эффективнее это можно сделать.

Пожалуйста, прокомментируйте или ответьте более эффективный подход.

1 голос
/ 14 февраля 2020
x = [1, 2, 3]
y = [[4, 5], [6, 7], [8, 9]]

result = [(i[0], i[1][0]) for i in zip(x,y)] + [(i[0], i[1][1]) for i in zip(x,y)]

Выход:

[(1, 4), (2, 6), (3, 8), (1, 5), (2, 7), (3, 9)]
0 голосов
/ 14 февраля 2020

Используются только итераторы, использующие itertools.chain.from_iterable

import itertools

x = [1, 2, 3]
y = [[4, 5], [6, 7], [8, 9]]

list(zip(list(itertools.chain.from_iterable(itertools.repeat(n, 2) for n in x)),
     list(itertools.chain.from_iterable(y))))

Вывод

[(1, 4), (1, 5), (2, 6), (2, 7), (3, 8), (3, 9)]

Это должно быть быстрее при длительной работе, ИМХО.

0 голосов
/ 14 февраля 2020

Вариант вашего подхода repeat и reshape:

In [89]: x = [1, 2, 3] 
    ...: y = [[4, 5], [6, 7], [8, 9]]                                                          
In [90]: res = np.zeros((3,2,2),int)                                                           
In [91]: res[:,:,1]=y                                                                          
In [92]: res[:,:,0]=np.array(x)[:,None]                                                        
In [93]: res                                                                                   
Out[93]: 
array([[[1, 4],
        [1, 5]],

       [[2, 6],
        [2, 7]],

       [[3, 8],
        [3, 9]]])
In [94]: res.reshape(6,2)                                                                      
Out[94]: 
array([[1, 4],
       [1, 5],
       [2, 6],
       [2, 7],
       [3, 8],
       [3, 9]])

Он использует broadcasting для отображения x и y в массив res.

0 голосов
/ 14 февраля 2020

Вдохновленный подходом 5 здесь :

from functools import reduce

x = [1, 2, 3]
y = [[4, 5], [6, 7], [8, 9]]

def listOfTuples(l1, l2): 
    l = list(map(lambda x, y:[(x,y[0]), (x,y[1])], l1, l2))
    m = reduce(lambda x, y: x + y, l)
    return(m)

r = listOfTuples(x, y)

Дает

[(1, 4), (1, 5), (2, 6), (2, 7), (3, 8), (3, 9)]
...