LoginSignup
1
1

More than 1 year has passed since last update.

pandas.Seriesで、値の型が揃っていないときの動き

Last updated at Posted at 2022-11-10

環境

  • pandas v1.5.1
  • Python v3.10.2

概要

pandas.Sereisで、値の型が揃っていないときの動きにハマりました。
後学のため、値の型が揃っていないときの動きをまとめます。

値の型が揃っていないときの挙動

dtypestringpandas.Seriesに、文字列以外を代入

dtypestringpandas.Seriesに対して数値またはbool値を代入しようとすると、ValueErrorが発生します。

In [167]: s1 = pandas.Series(["a", "b"], dtype="string")

In [168]: s1
Out[168]: 
0    a
1    b
dtype: string

In [169]: s1[0] = 1
---------------------------------------------------------------------------
ValueError: Cannot set non-string value '1' into a StringArray.

In [170]: s1[0] = True
---------------------------------------------------------------------------
ValueError: Cannot set non-string value 'True' into a StringArray.

数値と文字列のlistからpandas.Series(dtype="string")を生成

数値と文字列のlistからpandas.Seriesを生成する際、dtype="string"を指定すると、数値は文字列に変換されます。

In [198]: s2 = pandas.Series([1, "b"], dtype="string")

In [199]: s2
Out[199]: 
0    1
1    b
dtype: string

In [200]: type(s2[0])
Out[200]: str

dtypeint64pandas.Seriesに、文字列を代入

dtypeint64pandas.Seriesに対して文字列を代入すると、dtypeobjectに変わります。エラーは発生しません。

In [202]: s3 = pandas.Series([1, 2])

In [203]: s3
Out[203]: 
0    1
1    2
dtype: int64

In [204]: s3[0] = "a"

In [205]: s3
Out[205]: 
0    a
1    2
dtype: object

dtypeInt64pandas.Seriesに、文字列を代入

dtypeInt64pandas.Seriesに対して文字列、bool値、小数を代入すると、TypeErrorが発生します。
小数を代入してもエラーになるところが、nullableな型の特徴です。

In [211]: s4 = pandas.Series([1, 2], dtype="Int64")

In [212]: s4
Out[212]: 
0    1
1    2
dtype: Int64

In [213]: s4[0] = "a"
---------------------------------------------------------------------------
TypeError: Invalid value 'a' for dtype Int64

In [214]: s4[0] = True
---------------------------------------------------------------------------
TypeError: Invalid value 'True' for dtype Int64

In [279]: s4[0] = 1.2
---------------------------------------------------------------------------
TypeError: Invalid value '1.2' for dtype Int64

数値と文字列のlistからpandas.Series(dtype="int64")を生成

数値と文字列のlistからpandas.Seriesを生成する際、dtype="int64"を指定すると、数値に変換できるならエラーは発生しません。ただし警告メッセージが表示されます。

In [260]: s5 = pandas.Series([1, "b"], dtype="int64")
---------------------------------------------------------------------------
ValueError: invalid literal for int() with base 10: 'b'

n [272]: s5 = pandas.Series([1, "2"], dtype="int64")
/home/vagrant/.pyenv/versions/3.10.2/lib/python3.10/site-packages/numpy/core/numeric.py:2463: FutureWarning: elementwise comparison failed; returning scalar instead, but in the future will perform elementwise comparison
  return bool(asarray(a1 == a2).all())
<ipython-input-272-ddb554c61a9c>:1: FutureWarning: Values are too large to be losslessly cast to int64. In a future version this will raise OverflowError. To retain the old behavior, use pd.Series(values).astype(int64)
  s5 = pandas.Series([1, "2"], dtype="int64")

 [274]: s5
Out[274]: 
0    1
1    2
dtype: int64

まとめ

各挙動を確認した結果、以下であることが分かりました。

  • Int64, stringなどnullableな型に対して異なる値を代入しようとしたら、エラーが発生しました。ただし発生するエラーはTypeErrorValueErrorで、それぞれ異なりました。
  • int64などnullableでない型に対して、異なる値を代入すると、より広い範囲を表す型に変わります。
  • pandas.Series生成時には、dtype引数で指定した型に変換を試みます。変換できない場合はエラーが発生します。

補足

pandas.Series生成時にdtype="string"を指定しない場合

pandas.Seriesに文字列のlistを渡した場合、dtypeを指定しなければdtypeobjectになります。
objectは最も汎用的な型なので、この場合は異なる値を代入してもエラーは発生しません。

[206]: s5 = pandas.Series(["a", "b"])

In [207]: s5
Out[207]: 
0    a
1    b
dtype: object

In [208]: s5[0] = 1

In [209]: s5
Out[209]: 
0    1
1    b
dtype: object

In [210]: type(s5[0])
Out[210]: int
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1