Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

numpyで文字列の配列を作る際の注意点

More than 1 year has passed since last update.

はじめに

後世の人たちが私のような愚かなはまり方をしないよう、この書を残す。

問題

データ型を指定せず文字列の配列を作ると、それはUなんたらというdtypeになる。
dtype=strと指定しても同様。

ソース
import numpy as np
arr=np.array(["A","AB","ABC","ABCD"],dtype=str)
print (arr)
print (arr.dtype)
結果
['A' 'AB' 'ABC' 'ABCD']
<U4

不等号はリトルエンディアンを、UはUnicodeを意味し、数値は文字数を示す。つまり、変数の文字数が固定されているのだ。
後で加工された文字列の文字数がこの値を超過するとはみ出た分は失われてしまう。

ソース
arr[1]=arr[1]+"XYZ"
print (arr[1])

arr[2]="XYZ"+arr[2]
print (arr[2])

arr[3]="まったく別の文字列"
print (arr[3])
結果
ABXY # "AB"+"XYZ"だが"ABXYZ"ではない
XYZA # "XYZ"+"ABC"だが"XYZABC"ではない
まったく # "まったく別の文字列"ではない

これはnp.fullやnp.emptyでも同様。

ソース
arr1=np.array(["A","B","C"])
arr2=np.array(["X","Y","Z"])
arr=np.empty(3,dtype=str)
for i in range(3):
  arr[i]=arr1[i]+arr2[i]

print(arr)
結果
['A' 'B' 'C']

np.emptyで確保されたのは1文字分だけなので、AXやBYやCZを格納することができないわけだ。
2文字以上の文字列でもってnp.fullしたときもdtype=strを指定すると1文字になってしまう。さすがにこれは意味不明だ。

ソース
# dtype=strを指定した場合
arr=np.full(3,"ABC",dtype=str)
print (arr)
print (arr.dtype)
結果
['A' 'A' 'A']  # ["ABC" "ABC" "ABC"]になってくれない
<U1  # 1文字分しか確保されていない
ソース
# dtypeを明示しない場合
arr=np.full(3,"ABC")
print (arr)
print (arr.dtype)
結果
['ABC' 'ABC' 'ABC']  # 正しく定義されるが
<U3  # 文字数が決まっているので加工しづらいことに変わりはない

対策

任意の文字数の文字列を格納できるようにするには、dtype=str でなくdtype=objectと指定する。

ソース
arr=np.array(["A","AB","ABC","ABCD"],dtype=object)

arr[1]=arr[1]+"XYZ"
print (arr[1])

arr[2]="XYZ"+arr[2]
print (arr[2])

arr[3]="まったく別の文字列"
print (arr[3])
結果
ABXYZ
XYZABC
まったく別の文字列

次回予告

もともとは、Excelのセル番地を模した

[['A0' 'B0' 'C0' 'D0' 'E0']
 ['A1' 'B1' 'C1' 'D1' 'E1']
 ['A2' 'B2' 'C2' 'D2' 'E2']
 ['A3' 'B3' 'C3' 'D3' 'E3']]

といった配列を手打ちでなくプログラムで作成して、それを元にnumpyのスライスやOpenCVの画像トリミングについて勉強するつもりだった。
ところがうまくいかず、「文字列の連結は+だよな? 文字列と数値は連結できないのでstr()を使うんだよな?」と基本に立ち返っても駄目で、ググりまくって今回の発見に至った次第。
次こそはスライスの勉強をするぞ。

mo256man
日曜プログラマー。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away