94600


Decimal型の数値を含むDataFrame(Series)を、matplotlibでグラフ表示したいのですが、  
Decimal型そのままのデータではエラーとなり、グラフ表示できないようです。  
そこで、float型に変換しグラフ表示したいのですが、それぞれの列がDecimal型であるか判定するにはどうしたらよいでしょうか？  
pd.Series.dtypeでは、object型と表示されてしまい判断できないようです。  
要素まで参照しなければ、分からないものなのでしょうか？

[code]

    import decimal
    import pandas as pd
    
    df = pd.DataFrame(
        data=[
            {'aa': 'A0', 'bb': 100.1, 'cc': decimal.Decimal('100.1')},
            {'aa': 'A1', 'bb': 200.2, 'cc': decimal.Decimal('200.2')},
            {'aa': 'A2', 'bb': 250.9, 'cc': decimal.Decimal('250.9')},
        ],
        index=[
            pd.Timestamp('2023/04/01', tz='Asia/Tokyo'),
            pd.Timestamp('2023/04/02', tz='Asia/Tokyo'),
            pd.Timestamp('2023/04/03', tz='Asia/Tokyo'),
        ]
    )
    
    df.info()
    display(df)
    print(f"cc列のdtype:[{df['cc'].dtype}]")
    # ↑DataFrameもしくはSeriesからでは、object型と表示されてしまうので、
    # Decimal型かどうか判定できない？
    
    for item in df['cc']:
        print(type(item), item)
    
[/code]

↓確認用コードの実行結果です。  
[![画像の説明をここに入力](https://i.stack.imgur.com/lJfiB.png)](https://i.stack.imgur.com/lJfiB.png)

【追記】  
以下のように、Seriesを抽出してplotするとエラーが発生します。  
多数の列があり、どの列がどの型か分からなくて、質問しました。

[code]

    import decimal
    import pandas as pd
    
    df = pd.DataFrame(
        data=[
            {'aa': 'A0', 'bb': 100.1, 'cc': decimal.Decimal('100.1')},
            {'aa': 'A1', 'bb': 200.2, 'cc': decimal.Decimal('200.2')},
            {'aa': 'A2', 'bb': 250.9, 'cc': decimal.Decimal('250.9')},
        ],
        index=[
            pd.Timestamp('2023/04/01', tz='Asia/Tokyo'),
            pd.Timestamp('2023/04/02', tz='Asia/Tokyo'),
            pd.Timestamp('2023/04/03', tz='Asia/Tokyo'),
        ]
    )
    
    # ax = df['bb'].plot()  # ←正しくグラフが書ける
    # ax = df['cc'].plot()  # ←エラー（no numeric data to plot）が発生する。
    ax = df['cc'].astype(float).plot()  # ←正しくグラフが書ける
    
[/code]


CC BY-SA 4.0
2023-04-21T11:08:07.550
94595
2023-04-21T13:41:09.060
2023-04-21T11:45:52.050
35267
35267
question
python python3 pandas
PandasのDataFrame(Series)で、Decimal型を含む列を検出する方法


変換するだけなら以下のように

[code]

    df['cc_float'] = df['cc'].astype(float)
    
    df.iloc[1,1] = 207
    df.plot()
    
[/code]

[![plot](https://i.stack.imgur.com/Bn9jC.png)](https://i.stack.imgur.com/Bn9jC.png)


CC BY-SA 4.0
2023-04-21T11:34:15.927
94596
2023-04-21T11:34:15.927
43025
94595
answer


下記のようなコードで型変換するのはどうでしょうか？

[code]

    df2 = df.applymap(lambda x: float(x) if type(x) == decimal.Decimal else x)
    print(df2.dtypes)
    # aa     object
    # bb    float64
    # cc    float64
    # dtype: object
    
[/code]


CC BY-SA 4.0
2023-04-21T12:24:07.087
94599
2023-04-21T12:24:07.087
39819
94595
answer


> Decimal型を含む列
[code]

    dfx = df.applymap(type).eq(decimal.Decimal)
    col = dfx.loc[:, dfx.any()].columns
    print(col)
    
    # ['cc']
    
[/code]


CC BY-SA 4.0
2023-04-21T13:03:06.433
94600
2023-04-21T13:03:06.433
47127
94595
answer


Decimal型を検出する方法ではないですが、エラーを無視して変換することで、  
パフォーマンスの低下をおさえつつ、グラフ表示できるようになりました。  
df[col_name] = df[col_name].astype(float, errors='ignore')

[code]

    import decimal
    import pandas as pd
    
    df = pd.DataFrame(
        data=[
            {'aa': 'A0', 'bb': 100.1, 'cc': decimal.Decimal('100.1')},
            {'aa': 'A1', 'bb': 200.2, 'cc': decimal.Decimal('200.2')},
            {'aa': 'A2', 'bb': 250.9, 'cc': decimal.Decimal('250.9')},
        ],
        index=[
            pd.Timestamp('2023/04/01', tz='Asia/Tokyo'),
            pd.Timestamp('2023/04/02', tz='Asia/Tokyo'),
            pd.Timestamp('2023/04/03', tz='Asia/Tokyo'),
        ]
    )
    
    df.info()
    print('')
    
    for col_name in df:
        df[col_name] = df[col_name].astype(float, errors='ignore')
    df.info()
    
[/code]


CC BY-SA 4.0
2023-04-21T13:41:09.060
94601
2023-04-21T13:41:09.060
35267
94595
answer