Обновление: См. Ответ Ларсмана на этот вопрос: Numpy недавно добавил модуль numpy.char
для базовых строковых операций.
Краткий ответ: Numpy не предоставляет векторизованные строковые операции.Идиоматический способ - сделать что-то вроде (где Arr
- ваш массив numpy):
print '.'.join(item.upper() for item in Arr['strings'])
Длинный ответ, вот почему numpy не обеспечивает векторизованные строковые операции: (и хороший толчокмежду)
Один размер не подходит всем, когда речь идет о структурах данных.
Ваш вопрос, вероятно, кажется странным людям, пришедшим из не относящегося к области языка программирования, но это имеет большой смысл для людей, пришедших из предметно-ориентированного языка.
Python предоставляет вам широкий выбор структур данных.Некоторые структуры данных лучше в некоторых задачах, чем другие.
Во-первых, массивы numpy не являются контейнером «hold-all» по умолчанию в python.Встроенные контейнеры Python очень хороши для того, для чего они предназначены.Часто вам нужен список или диктовка.
Numpy's ndarray
s для однородных данных.
В двух словах, numpy не имеет векторизациистроковые операции.
ndarray
s - это специализированный контейнер, предназначенный для хранения N-мерных однородных групп элементов в минимально возможном объеме памяти.Акцент действительно делается на минимизации использования памяти (я пристрастен, потому что это в основном то, что мне нужно, но это полезный способ думать об этом.).Векторизованные математические операции - просто приятный побочный эффект хранения вещей в непрерывном блоке памяти.
Строки обычно имеют разную длину.
Например ['Dog', 'Cat', 'Horse']
.Numpy использует подобный базе данных подход, требующий от вас определения длины для ваших строк, но простой факт, что строки не должны быть фиксированной длины, имеет много последствий.
Большинство полезных строковых операций returnстроки переменной длины.(например, '.'.join(...)
в вашем примере)
Те, которые не (например, верхний и т. д.), вы можете имитировать с другими операциями, если хотите.(Например, верхний - примерно (x.view(np.uint8) - 32).view('S1')
. Я не рекомендую вам это делать, но вы можете ...)
В качестве основного примера: 'A' + 'B'
дает 'AB'
.'AB'
отличается от длины 'A'
или 'B'
.Numpy имеет дело с другими вещами, которые делают это (например, np.uint8(4) + np.float(3.4)
), но строки гораздо более гибки по длине, чем числа.(Правила «Upcasting» и «downcasting» для чисел довольно просты.)
Другая причина, по которой numpy не делает этого, заключается в том, что основное внимание уделяется числовым операциям.'A'**2
не имеет конкретного определения в python (вы, конечно, можете создать строковый класс, но каким он должен быть?).Строковые массивы являются гражданами второго сорта в NumPy.Они существуют, но большинство операций для них не определены.
Python уже действительно хорошо справляется с обработкой строк
Другие (идействительно, главная причина, по которой numpy не пытается предлагать строковые операции, заключается в том, что python уже действительно хорош в этом.
Списки - это фантастические гибкие контейнеры.Python имеет огромный набор очень хороших, очень быстрых строковых операций.Постижения списков и выражения генераторов довольно быстрые, и они не испытывают лишних усилий, пытаясь угадать, каким должен быть тип или размер возвращаемого элемента, поскольку им все равно.(Они просто хранят указатель на него.)
Кроме того, итерация по пустым массивам в python медленнее, чем итерация по списку или кортежу в python, но для строковых операций вам действительно лучше всего использовать обычные выражения списка / генератора. (например, print '.'.join(item.upper() for item in Arr['strings'])
в вашем примере) Еще лучше, не используйте вначале массивы для хранения строк. Это имеет смысл, если у вас есть один столбец структурированного массива со строками, но это все. Python предоставляет вам очень богатых и гибких структур данных. Массив Numpy - это не конец и не конец, а специализированный случай, а не обобщенный случай.
Кроме того, имейте в виду, что большую часть того, что вы хотели бы сделать с массивом numpy
Учите Python, а не только Numpy
Я не пытаюсь быть здесь дерзким, но работа с массивами-пустышками очень похожа на многие вещи в Matlab, R или IDL и т. Д.
Это знакомая парадигма, и любой первый инстинкт должен попытаться применить ту же самую парадигму к остальной части языка.
Python намного больше, чем просто тупица. Это мультипарадигмальный язык, поэтому легко придерживаться тех парадигм, к которым вы уже привыкли. Попробуйте научиться «думать в питоне», а также просто «думать в ноль». Numpy предоставляет определенную парадигму для python, но там гораздо больше, и некоторые парадигмы лучше подходят для некоторых задач, чем другие.
Отчасти это становится знакомством с сильными и слабыми сторонами различных контейнеров данных (списки против диктов против кортежей и т. Д.), А также с различными парадигмами программирования (например, объектно-ориентированные, функциональные и процедурные и т. Д.).
В целом, Python имеет несколько различных типов специализированных структур данных. Это несколько отличает его от предметно-ориентированных языков, таких как R или Matlab, которые имеют несколько типов структур данных, но сосредоточены на выполнении всего с одной определенной структурой. (Мой опыт работы с R ограничен, поэтому я могу ошибаться, но в любом случае это мое впечатление об этом. Во всяком случае, это верно для Matlab.)
Во всяком случае, я не пытаюсь рутовать здесь, но мне потребовалось довольно много времени, чтобы перестать писать Фортран в Matlab, и мне потребовалось еще больше времени, чтобы перестать писать Matlab на python. Этот бессмысленный ответ очень нагляден на конкретных примерах, но, надеюсь, он по крайней мере немного разумен и несколько помогает.