質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.84%

  • Python

    6383questions

    Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

  • pandas

    415questions

    Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。

pandasのDataFrameにSeriesを特定の場合において追加できない

解決済

回答 1

投稿

  • 評価
  • クリップ 1
  • VIEW 441

kamome283

score 32

はじめまして
PandasのDataFrameにSeriesを結合する際に、特定の場合においてエラーが出て困っています。
具体的には、結合するSeriesの一つの値をNaNからpd.Timestampクラスの値に変えたものを追加しようとするとエラーが出てしまいます。
以下が具体的な問題です。

発生している問題・エラーメッセージ

初期のデータフレームは以下のようなものです。
last_updateの値はpd.Timestampクラスです。

    In [9]: df
    Out[9]: 
      importance interval last_read                last_update    name trigger
    0          2      NaN       NaN  2017-12-09 00:00:00+09:00  foobar     NaN

ここでは、追加するシリーズをデータフレームの1行目と同じものだとします。

    In [10]: record = df.iloc[0].copy()

このシリーズをデータフレームに追加する場合はなんの問題も起きません。

    In [11]: df.append(record)
    Out[11]: 
      importance interval last_read                last_update    name trigger
    0          2      NaN       NaN  2017-12-09 00:00:00+09:00  foobar     NaN
    0          2      NaN       NaN  2017-12-09 00:00:00+09:00  foobar     NaN


今度はシリーズの一つの値(intervalの値をNaNから1に)を変えたものを追加してみますが、これも問題は起こりません。

    In [12]: record['interval'] = 1

    In [13]: df.append(record)
    Out[13]: 
      importance interval last_read                last_update    name trigger
    0          2      NaN       NaN  2017-12-09 00:00:00+09:00  foobar     NaN
    0          2        1       NaN  2017-12-09 00:00:00+09:00  foobar     NaN


次に、上のシリーズの値をもう一つ(triggerをNaNからpd.Timestampクラスの値に)変えたものを追加してみると、エラーが出ます。

    In [10]: record
    Out[10]: 
    importance                             2
    interval                             NaN
    last_read                            NaN
    last_update    2017-12-09 00:00:00+09:00
    name                              foobar
    trigger                              NaN
    Name: 0, dtype: object

    In [11]: record['trigger'] = record['last_update']

    In [12]: record
    Out[12]: 
    importance                             2
    interval                             NaN
    last_read                            NaN
    last_update    2017-12-09 00:00:00+09:00
    name                              foobar
    trigger        2017-12-09 00:00:00+09:00
    Name: 0, dtype: object

    In [13]: df.append(record)
    ---------------------------------------------------------------------------
    TypeError                                 Traceback (most recent call last)
    <ipython-input-13-7c027f1cbb54> in <module>()
    ----> 1 df.append(record)

    ~/anaconda3/lib/python3.6/site-packages/pandas/core/frame.py in append(self, other, ignore_index, verify_integrity)
       4545             to_concat = [self, other]
       4546         return concat(to_concat, ignore_index=ignore_index,
    -> 4547                       verify_integrity=verify_integrity)
       4548 
       4549     def join(self, other, on=None, how='left', lsuffix='', rsuffix='',

    ~/anaconda3/lib/python3.6/site-packages/pandas/core/reshape/concat.py in concat(objs, axis, join, join_axes, ignore_index, keys, levels, names, verify_integrity, copy)
        205                        verify_integrity=verify_integrity,
        206                        copy=copy)
    --> 207     return op.get_result()
        208 
        209 

    ~/anaconda3/lib/python3.6/site-packages/pandas/core/reshape/concat.py in get_result(self)
        405             new_data = concatenate_block_managers(
        406                 mgrs_indexers, self.new_axes, concat_axis=self.axis,
    --> 407                 copy=self.copy)
        408             if not self.copy:
        409                 new_data._consolidate_inplace()

    ~/anaconda3/lib/python3.6/site-packages/pandas/core/internals.py in concatenate_block_managers(mgrs_indexers, axes, concat_axis, copy)
       4830     blocks = [make_block(
       4831         concatenate_join_units(join_units, concat_axis, copy=copy),
    -> 4832         placement=placement) for placement, join_units in concat_plan]
       4833 
       4834     return BlockManager(blocks, axes)

    ~/anaconda3/lib/python3.6/site-packages/pandas/core/internals.py in <listcomp>(.0)
       4830     blocks = [make_block(
       4831         concatenate_join_units(join_units, concat_axis, copy=copy),
    -> 4832         placement=placement) for placement, join_units in concat_plan]
       4833 
       4834     return BlockManager(blocks, axes)

    ~/anaconda3/lib/python3.6/site-packages/pandas/core/internals.py in concatenate_join_units(join_units, concat_axis, copy)
       4937     to_concat = [ju.get_reindexed_values(empty_dtype=empty_dtype,
       4938                                          upcasted_na=upcasted_na)
    -> 4939                  for ju in join_units]
       4940 
       4941     if len(to_concat) == 1:

    ~/anaconda3/lib/python3.6/site-packages/pandas/core/internals.py in <listcomp>(.0)
       4937     to_concat = [ju.get_reindexed_values(empty_dtype=empty_dtype,
       4938                                          upcasted_na=upcasted_na)
    -> 4939                  for ju in join_units]
       4940 
       4941     if len(to_concat) == 1:

    ~/anaconda3/lib/python3.6/site-packages/pandas/core/internals.py in get_reindexed_values(self, empty_dtype, upcasted_na)
       5210                     pass
       5211                 else:
    -> 5212                     missing_arr = np.empty(self.shape, dtype=empty_dtype)
       5213                     missing_arr.fill(fill_value)
       5214                     return missing_arr

    TypeError: data type not understood


"data type not understood"とあるので、もしかしてpd.Timestampクラスの値は使えないのかとも思いましたが、以下のように問題なく新規にデータフレームを作ることは可能でした。

In [5]: a = pd.Timestamp('today')

In [6]: b = pd.Timestamp('today') + pd.tseries.offsets.Day(2)

In [7]: date = [a, b]

In [8]: name = ['foo', 'bar']

In [9]: df = pd.DataFrame({'date': date, 'name': name})

In [10]: df
Out[10]: 
                        date name
0 2017-12-10 17:56:29.315316  foo
1 2017-12-12 17:56:37.535777  bar


初心者のため、これが仕様なのかそれとも何らかのバグ、それとも単に自分の思い違いなのかもわかりません。
熟練者の皆様、アドバイスよろしくお願いします。 

補足情報(言語/FW/ツール等のバージョンなど)

pandasのバージョンは0.20.3です。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+2

どうやらpandas の バグのようですね。

いろいろ試してみましたが、空の列にawareなDatetimeデータ(TimeZone付きdatetimeデータ)を追加すると、TypeError が発生するようです。

【実験コード】

import pandas as pd
df = pd.DataFrame(columns=['A','B'])
# TimeZone付きのDatetimeを追加でエラーが発生
df.append(pd.Series({'A':pd.Timestamp.now(tz='Asia/Tokyo'), 'B':1}), ignore_index=True) # <= TypeError
# TimeZoneが無いと問題ない
df.append(pd.Series({'A':pd.Timestamp.now(), 'B':1}), ignore_index=True)

ということで、Bug Report を探してみたところありました。

https://github.com/pandas-dev/pandas/issues/16044

残念ながら、次のメジャーリリースまで直らなそうですね。
とりあえずは

・ nativeなdatetimeを使う
・ 空のカラムにawareなdatateimeデータを入れるときは、予め適当なデータを入れておく

あたりで逃げるしかないのではないでしょうか

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/11 21:19

    検証、バグレポート付きの簡潔でわかりやすい回答をいただき、本当にありがとうございます。
    教えていただいた2番目のやり方でとりあえずは問題をしのぎたいと思います。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.84%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • Python

    6383questions

    Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

  • pandas

    415questions

    Pandasは、PythonでRにおけるデータフレームに似た型を持たせることができるライブラリです。 行列計算の負担が大幅に軽減されるため、Rで行っていた集計作業をPythonでも比較的簡単に行えます。 データ構造を変更したりデータ分析したりするときにも便利です。