In [2]: import pandas as pd
In [3]: df = pd.DataFrame({'col': ['abc', 'def']})
...: mapping = {v: k for k, v in enumerate('abcdef')}
...: df['new'] = df['col'].apply(lambda x: list(x))
In [7]: df['new']
Out[7]:
0 [a, b, c]
1 [d, e, f]
Name: new, dtype: object
In [8]: df['new'].values
Out[8]: array([list(['a', 'b', 'c']), list(['d', 'e', 'f'])], dtype=object)
np.stack
ведет себя подобно np.array
, объединяя элементы на новой начальной оси:
In [9]: np.stack(df['new'].values)
Out[9]:
array([['a', 'b', 'c'],
['d', 'e', 'f']], dtype='<U1')
или на другой оси, которую вы выбираете:
In [10]: np.stack(df['new'].values, axis=1)
Out[10]:
array([['a', 'd'],
['b', 'e'],
['c', 'f']], dtype='<U1')
[ 1118] np.array
также работает, если массив объектов превращается в список (как показывает @coldspeed):
In [11]: df['new'].values.tolist()
Out[11]: [['a', 'b', 'c'], ['d', 'e', 'f']]
In [12]: np.array(df['new'].values.tolist())
Out[12]:
array([['a', 'b', 'c'],
['d', 'e', 'f']], dtype='<U1')
Что касается скорости, давайте сделаем больший массив:
In [16]: arr = np.frompyfunc(lambda x: np.arange(1000),1,1)(np.arange(1000))
In [17]: arr.shape
Out[17]: (1000,)
In [18]: np.stack(arr).shape
Out[18]: (1000, 1000)
In [20]: np.array(arr.tolist()).shape
Out[20]: (1000, 1000)
In [21]: timeit np.stack(arr).shape
5.24 ms ± 190 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [22]: timeit np.array(arr.tolist()).shape
4.45 ms ± 138 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
[1120 В основном то же самое, с небольшим перевесом к подходу np.array
.
stack
подобно vstack
расширяет размеры каждого элемента по мере необходимости. Пропуск этого с concatenate
немного быстрее:
In [27]: timeit np.concatenate(arr).reshape(-1,1000).shape
4.04 ms ± 12.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
Этот arr
содержит массивы. Если вместо этого он содержит списки, подход array(arr.tolist())
работает лучше (относительно), поскольку у него есть только один список (списков) для преобразования в массив. Подход stack
должен сначала преобразовать каждый из подсписков в массивы.
Я запустил бы путем моделирования некоторых основных интерфейсов (в смысле ООП, не смысле GUI). Кажется мне, у Вас будет Узел, который примет набор исходных данных и единственного вывода. Вы не дали признака того, как широко типы данных, но Вы захотите некоторый подходящий метод представления Ваших исходных данных/выводов. Для Вашей первой цели это могло быть целым числом.
На некотором универсальном языке ООП стиля C (надейтесь, что он имеет смысл):
class Node<T> {
Node<T>[] inputs;
T eval();
}
class AdderNode extends Node<int> {
int eval() {
int accum = 0;
for (inputs : i)
accum += i.eval();
return i;
}
}
class ConstNode<int I> extends Node<int> {
int eval() { return I; }
}
AdderNode a;
a.inputs.add(ConstNode<2>());
a.inputs.add(ConstNode<3>());
a.eval();
Вы могли подробно остановиться на этом путем замены интервала некоторым абстрактным классом, универсальным, или интерфейсным. Фактическая реализация будет варьироваться на основе фактического языка, конечно.
Я запустил бы с моделирования интересных операций. В конечном счете Вы подключите их к UI, но это - руль и газовая педаль, не механизм.
То, что Вы пытаетесь создать, имеет много общего с языками программирования: переменные, значения, типы, выражения, оценка, и т.д. Многие метафоры применимы и могли бы обеспечить некоторое руководство.
При использовании.NET 3.5 у Вас есть опция Деревьев выражений, которые позволяют Вам представлять и компилировать выражения кода во времени выполнения.
Например, для моделирования первой цели:
using System.Linq.Expressions;
ConstantExpression theNumber2 = Expression.Constant(2);
ConstantExpression theNumber3 = Expression.Constant(3);
BinaryExpression add2And3 = Expression.Add(theNumber2, theNumber3);
Для вызова выражения мы должны перенестись add2And3
с методом. Это сделано с лямбда-выражением:
Expression<Func<int>> add2And3Lambda = Expression.Lambda<Func<int>>(add2And3);
Func<int>
представляет метод, который не берет параметров и возвращается int
. В C#, код, представленный add2And3Lambda
был бы:
() => 2 + 3
Таким образом, то, что мы имеем, является деревом выражений, корень которого является методом. Поскольку метод является вызываемым, мы можем скомпилировать дерево в экземпляр базового типа делегата:
Func<int> add2And3Func = add2And3Lambda.Compile();
Теперь мы можем вызвать код, который мы создали:
int theNumber5 = add2And3Func();
Каждое выражение, доступное языкам.NET, поддерживается.
Предположите, что каждый узел в Вашем графике имеет Expression
связанный с ним. Это могло бы дать Вам общее представление о питании деревьев выражений и как они могли помочь Вам с этой задачей.
Весь этот узел системы имеют общего это, они описывают язык функционального программирования. Функция берет несколько параметров и возвращает единственный результат, неважно, для того, какая цель она была разработана. Некоторые примеры:
Графика: Размытость (Изображение, Ядро, Радиус)-> Изображение
Математика: Добавьте (Число, Число)-> Реляционный Номер
: Фильтр (Таблица, Предикат)-> Таблица
В основном, которая сводится к функциональной подписи как Func<object[], object>
(C#).
Вы столкнетесь с вопросом того, как сделать Вашу систему узла персистентной. Вы хотите сделать результат узла применимым как параметр только еще одним узлом (дерево) или несколькими узлами (график)?
Пример дерева, непосредственно имейте параметры дочерние узлы:
Add(
Multiply(
Constant(5),
Constant(4)
),
Multiply(
Constant(5),
Constant(3)
)
)
Пример графика, сохраните все узлы в списке и только используйте ссылки:
A := Constant(5)
B := Constant(4)
C := Constant(3)
D := Func(Multiply, A, B)
E := Func(Multiply, A, C)
F := Func(Add, D, E)
Может, у bwise есть что-нибудь интересное?
В нижней половине этой страницы показан пример использования bwise для создания блока умножения, который принимает в качестве входных данных два числа.
Я нашел полезную информацию о реализации такого интерфейса в Какао: