it-swarm.com.de

Python Pandas - Ändern einiger Spaltentypen in Kategorien

Ich habe die folgende CSV-Datei in iPython Notebook eingegeben:

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

Ich habe auch Pandas als pd importiert, numpy als np und matplotlib.pyplot als plt. Die folgenden Datentypen sind vorhanden (das Folgende ist eine Zusammenfassung - es gibt ungefähr 100 Spalten)

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

Ich möchte "Parks", "Spielplätze", "Sport" und "Roading" in Kategorien umwandeln (in ihnen sind gleichwertige Antworten vorhanden.) Jede Spalte enthält jedoch unterschiedliche Arten von Antworten (z. B. "man stimmt zu") "usw., ein anderer hat" sehr wichtig "," wichtig "usw.), der Rest bleibt als int64. 

Ich konnte einen separaten Dataframe - public1 - erstellen und eine der Spalten mithilfe des folgenden Codes in einen Kategorietyp ändern:

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

Als ich jedoch versuchte, eine Nummer mit diesem Code auf einmal zu ändern, war ich nicht erfolgreich:

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

Trotzdem möchte ich keinen separaten Datenrahmen nur mit den Kategoriespalten erstellen. Ich möchte, dass sie im ursprünglichen Datenrahmen geändert wurden.

Ich habe zahlreiche Möglichkeiten ausprobiert, um das zu erreichen, dann habe ich den Code hier ausprobiert: Pandas: Datentyp der Spalten ändern ...

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

und bekam folgenden Fehler:

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

Gibt es eine Möglichkeit, "Parks", "Spielplätze", "Sport", "Roading" in Kategorien zu ändern (damit die Antworten der Likert-Skala analysiert werden können), so dass "Einwohner" und "Kinder" (und die 94 anderen Spalten) übrig bleiben sind string, int + floats) bitte unberührt? Oder gibt es einen besseren Weg, dies zu tun? Wenn jemand Anregungen und/oder Rückmeldungen hat, wäre ich sehr dankbar.

Vielen Dank im Voraus.

zum Hinzufügen bearbeitet - Ich benutze Python 2.7.

28
gincard

Manchmal müssen Sie nur eine for-Schleife verwenden:

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

Sie können die pandas.DataFrame.apply-Methode zusammen mit einem lambda-Ausdruck verwenden, um das Problem zu lösen. In Ihrem Beispiel könnten Sie verwenden 

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

Ich kenne keinen Weg, um dieses Inplace auszuführen, daher ende ich normalerweise mit einem solchen Element:

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

Natürlich können Sie .select_dtypes durch explizite Spaltennamen ersetzen, wenn Sie nicht alle einen bestimmten Datentyp auswählen möchten (in Ihrem Beispiel scheint es jedoch so, als wollten Sie alle object-Typen haben).

30
Derek Kaknes

Ab pandas 0.19.0 beschreibt What's New , dass read_csv das Analysieren von Categorical-Spalten direkt unterstützt .. Diese Antwort gilt nur, wenn Sie von read_csv ausgehen auf 10.000 Datensätzen:

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 (oder> = 19.0 ohne Angabe von dtype)

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

Für gemischtes dtypes kann das Parsing als Categorical implementiert werden, indem ein Wörterbuch dtype={'colname' : 'category', ...} in read_csv übergeben wird.

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

Performance

Eine leichte Beschleunigung (lokales Jupyter-Notebook), wie in den Versionshinweisen erwähnt.

# 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
9
Kevin

Keine Notwendigkeit für Schleifen, Pandas kann es jetzt direkt tun, übergebe einfach eine Liste der zu konvertierenden Spalten und Pandas konvertiert sie alle.

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-Notizbuch

In meinem Fall hatte ich einen großen Datenrahmen mit vielen Objekten, die ich in eine Kategorie konvertieren möchte.

Daher habe ich die Objektspalten ausgewählt und alles, was NA ist, als fehlend ausgefüllt und dann im ursprünglichen DataFrame wie in gespeichert

# 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()

Ich hoffe, dass dies eine hilfreiche Ressource für spätere Referenz sein könnte

0
rsc05

Ich fand, dass die Verwendung einer for-Schleife gut funktioniert.

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