Me han alimentado el siguiente archivo CSV en iPython Notebook:

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

También he importado los pandas como pd, numpy, como np y matplotlib.pyplot como plt. Los siguientes tipos de datos están presentes (el siguiente es un resumen – hay alrededor de 100 columnas)

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

Quiero cambiar de ‘parques’, ‘playgrounds’, ‘deportes’ y ‘la carretera’ a categorías (tienen escala de likert de respuestas en cada columna tiene diferentes tipos de likert respuestas aunque (por ejemplo, uno tiene «muy de acuerdo», «de acuerdo», etc., otro tiene «muy importante», «importante», etc.), dejando el resto como int64.

Yo era capaz de crear un dataframe – public1 de espacio de nombres y el cambio de una de las columnas para un tipo de categoría usando el siguiente código:

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

Sin embargo, cuando he intentado cambiar de un número a la vez el uso de este código, no tuve éxito:

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

A pesar de esto, no quiero crear un dataframe con sólo las categorías de las columnas. Me gustaría cambiar en el original dataframe.

He intentado de muchas maneras para lograr esto, entonces probado el código aquí: Pandas: cambiar el tipo de datos de las columnas

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

y obtuve el siguiente error:

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

Hay una manera de cambiar ‘parques’, ‘playgrounds’, ‘deportes’, ‘la carretera’ a las categorías (de modo que la escala de likert, las respuestas pueden ser analizados), dejando a ‘residente’ y ‘niños’ (y el 94 otras columnas que son string, int + flotadores) sin tocar, por favor? O, ¿hay una manera mejor de hacer esto? Si alguien tiene alguna sugerencia y/o comentarios me quedaría muy agradecido….poco a poco estoy quedando calvo ripeo de mi pelo!

Muchas gracias de antemano.

editado para añadir – estoy usando Python 2.7.

InformationsquelleAutor gincard | 2015-03-07

6 Comentarios

  1. 68

    A veces, sólo tiene que utilizar un for-loop:

    for col in ['parks', 'playgrounds', 'sports', 'roading']:
        public[col] = public[col].astype('category')
    • Muchas gracias @unutbu, esto ha funcionado de maravilla. No puedo creer que es así de simple y me siento realmente estúpido ahora!
    • lo que si estoy recibiendo el error? /Usuarios/aire/anaconda/lib/python2.7/sitio-paquetes/ipykernel/__main__.py:7: SettingWithCopyWarning: Un valor está tratando de establecerse en una copia de un fragmento de un DataFrame. Trate de usar .loc[row_indexer,col_indexer] = valor en lugar de Ver las advertencias en la documentación: pandas.pydata.org/pandas-docs/stable/…
    • Usted puede conseguir que la UserWarning si public es un sub-DataFrame de otro DataFrame y tiene datos que copiar de que otros DataFrame. Por una abundancia de precaución, los Pandas emite un UserWarning para advertirle de que la modificación de public no modifica que otros DataFrame. Si la modificación que otros DataFrame no es lo que se pretende hacer o no es un problema, entonces usted es libre de ignorar el UserWarning. Si usted desea el silencio de la UserWarning de todos modos, el lugar public.is_copy = False antes de hacer las asignaciones de la forma public[col] = ....
    • gracias, yo no acababa de obtener de la documentación. Esto hace que sea claro. Como profunda y superficial copia en C++ derecho? Yo fundidas de las variables originales y, a continuación, se copian. O el uso.copia() al hacer el subconjunto funciona así, si alguien se enfrenta a este problema.
    • Sí, eso es correcto. public.copy() también funciona, pero tenga en cuenta que si public es un gran DataFrame, public.copy() podría ser mucho más lento que el ajuste de la bandera public.is_copy = False. (Por otra parte, la UserWarning sólo es relevante cuando public es una copia, por lo que parece irónico que tendríamos que hacer otra copia sólo para silenciar la alerta.) Por otro lado, no creo que public.is_copy = False está documentado. He encontrado mediante la lectura del código fuente. Así que si se pegue a la documentada de la API es una prioridad, es posible que desee utilizar public = public.copy().
  2. 36

    Puede utilizar el pandas.DataFrame.apply método, junto con una lambda expresión para solucionar esto. En su ejemplo, usted podría usar

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

    No sé de una forma de hacer esto directamente, por lo general, voy a terminar con algo como esto:

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

    Obviamente, usted puede reemplazar .select_dtypes con nombres de columna explícitos si usted no desea seleccionar todos los de un determinado tipo de datos (aunque en su ejemplo, parece que querían que todos los object tipos).

    • Excelente +1 ! Realmente python y concisa solución. También grande como la que se utiliza una consulta para obtener las columnas deseadas en lugar de pasar como una rígida matriz.
    • df = df.aplicar(lambda s: s.astype(‘categoría’) si s.nombre en [‘parques’, ‘playgrounds’, ‘deportes’] else s)
  3. 10

    Como de los pandas 0.19.0, Qué hay de Nuevo describe que read_csv apoya el análisis de Categorical las columnas directamente.
    Esta respuesta sólo se aplica si usted está empezando desde read_csv lo contrario, creo que unutbu la respuesta es aún mejor.
    Ejemplo de 10.000 registros:

    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 (o >=19.0 sin especificar 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

    Mixto dtypes el análisis de Categorical puede ser implementado por el paso de un diccionario dtype={'colname' : 'category', ...} en 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

    Rendimiento

    Una ligera speed-up (local jupyter notebook), como se menciona en las notas de la versión.

    # 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
  4. 5

    Sin necesidad de bucles, los Pandas se puede hacer directamente ahora, acaba de pasar una lista de columnas que desea convertir y Pandas va a convertir a todos.

    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. 0

    He encontrado que el uso de un bucle for funciona bien.

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

    Jupyter Notebook

    En mi caso, tuve grandes Dataframe con muchos objetos que me gustaría convertir a la categoría.

    Por lo tanto, lo que hice fue seleccionado el objeto columnas y lleno de nada de lo que es NA a los que faltan y después lo guardó en el original Dataframe como en

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

    Espero que este podría ser un recurso útil para la posterior referencia

Dejar respuesta

Please enter your comment!
Please enter your name here