web-dev-qa-db-ja.com

Python Pandas-一部の列タイプをカテゴリに変更する

次のCSVファイルをiPython Notebookにフィードしました。

public = pd.read_csv("categories.csv")
public

また、pandas pd、numpyをnp、matplotlib.pyplotをpltとしてインポートしました。以下のデータタイプが存在します(要約は約100列あります)

In [36]:   public.dtypes
Out[37]:   parks          object
           playgrounds    object
           sports         object
           roading        object               
           resident       int64
           children       int64

「公園」、「遊び場」、「スポーツ」、「道路」をカテゴリに変更します(リッカートスケールの応答があります-各列には異なるタイプのリッカート応答があります(たとえば、「強く同意する」、「同意する」 「など」、「その他」には「非常に重要」、「重要」など)があり、残りはint64のままです。

次のコードを使用して、別のデータフレーム-public1-を作成し、列の1つをカテゴリタイプに変更できました。

public1 = {'parks': public.parks}
public1 = public1['parks'].astype('category')

ただし、このコードを使用して一度に数値を変更しようとすると、失敗しました。

public1 = {'parks': public.parks,
           'playgrounds': public.parks}
public1 = public1['parks', 'playgrounds'].astype('category')

それにもかかわらず、カテゴリ列だけで別のデータフレームを作成したくありません。元のデータフレームで変更してほしい。

私はこれを達成するために多くの方法を試した後、次のコードを試しました: Pandas:change data type of columns ...

public[['parks', 'playgrounds', 'sports', 'roading']] = public[['parks', 'playgrounds', 'sports', 'roading']].astype('category')

次のエラーが発生しました:

 NotImplementedError: > 1 ndim Categorical are not supported at this time

「公園」、「遊び場」、「スポーツ」、「道路」をカテゴリに変更する方法はありますか(リッカートスケールの応答を分析できます)、「居住者」と「子供」(およびその他の94列文字列、int + float)はそのままにしてください。または、これを行うためのより良い方法はありますか?誰か提案やフィードバックがある場合は、私は最も感謝しています....ゆっくりと髪を引き裂くつもりです!

事前に感謝します。

追加するために編集-私はPython 2.7。

39
gincard

場合によっては、forループを使用する必要があります。

for col in ['parks', 'playgrounds', 'sports', 'roading']:
    public[col] = public[col].astype('category')
68
unutbu

これを解決するには、pandas.DataFrame.applyメソッドとlambda式を使用します。あなたの例では、使用できます

df[['parks', 'playgrounds', 'sports']].apply(lambda x: x.astype('category'))

私はこのインプレースを実行する方法を知らないので、通常は次のようなものになります:

df[df.select_dtypes(['object']).columns] = df.select_dtypes(['object']).apply(lambda x: x.astype('category'))

特定のデータ型をすべて選択したくない場合は、明らかに.select_dtypesを明示的な列名に置き換えることができます(例ではすべてのobject型が必要なようですが)。

35
Derek Kaknes

pandas 0.19.0、 新機能read_csvは、Categorical列の直接解析をサポートしています。この回答は、read_csvそれ以外の場合、私はunutbuの答えがまだ最高だと思います。 10,000レコードの例:

import pandas as pd
import numpy as np

# Generate random data, four category-like columns, two int columns
N=10000
categories = pd.DataFrame({
            'parks' : np.random.choice(['strongly agree','agree', 'disagree'], size=N),
            'playgrounds' : np.random.choice(['strongly agree','agree', 'disagree'], size=N),
            'sports' : np.random.choice(['important', 'very important', 'not important'], size=N),
            'roading' : np.random.choice(['important', 'very important', 'not important'], size=N),
            'resident' : np.random.choice([1, 2, 3], size=N),
            'children' : np.random.choice([0, 1, 2, 3], size=N)
                       })
categories.to_csv('categories_large.csv', index=False)

<0.19.0(またはdtypeを指定せずに> = 19.0)

pd.read_csv('categories_large.csv').dtypes # inspect default dtypes

children        int64
parks          object
playgrounds    object
resident        int64
roading        object
sports         object
dtype: object

> = 0.19.0

混合dtypesの場合、_Categoricalとして解析するには、辞書dtype={'colname' : 'category', ...} in read_csv

pd.read_csv('categories_large.csv', dtype={'parks': 'category',
                                           'playgrounds': 'category',
                                           'sports': 'category',
                                           'roading': 'category'}).dtypes
children          int64
parks          category
playgrounds    category
resident          int64
roading        category
sports         category
dtype: object

性能

リリースノートに記載されているように、若干の高速化(ローカルjupyterノートブック)。

# unutbu's answer
%%timeit
public = pd.read_csv('categories_large.csv')
for col in ['parks', 'playgrounds', 'sports', 'roading']:
    public[col] = public[col].astype('category')
10 loops, best of 3: 20.1 ms per loop

# parsed during read_csv
%%timeit
category_cols = {item: 'category' for item in ['parks', 'playgrounds', 'sports', 'roading']}
public = pd.read_csv('categories_large.csv', dtype=category_cols)
100 loops, best of 3: 14.3 ms per loop
10
Kevin

ループの必要はありません。Pandasは今すぐ直接行うことができます。変換したい列のリストを渡すだけで、Pandasはそれらをすべて変換します。

cols = ['parks', 'playgrounds', 'sports', 'roading']:
public[cols] = public[cols].astype('category')

df = pd.DataFrame({'a': ['a', 'b', 'c'], 'b': ['c', 'd', 'e']})

>>     a  b
>>  0  a  c
>>  1  b  d
>>  2  c  e

df.dtypes
>> a    object
>> b    object
>> dtype: object

df[df.columns] = df[df.columns].astype('category')
df.dtypes
>> a    category
>> b    category
>> dtype: object
5

Jupyterノートブック

私の場合、カテゴリに変換したい多くのオブジェクトを持つ大きなデータフレームがありました。

したがって、私がやったのは、オブジェクト列を選択し、欠落しているNAのすべてを埋めてから、元のデータフレームに保存します

# Convert Object Columns to Categories
obj_df =df.select_dtypes(include=['object']).copy()
obj_df=obj_df.fillna('Missing')
for col in obj_df:
    obj_df[col] = obj_df[col].astype('category')
df[obj_df.columns]=obj_df[obj_df.columns]
df.head()

これが後の参考に役立つリソースになることを願っています

0
rsc05

Forループを使用するとうまくいくことがわかりました。

for col in ['col_variable_name_1', 'col_variable_name_2', ect..]:
    dataframe_name[col] = dataframe_name[col].astype(float)
0
NickTumi