¿Cómo convertir un conjunto de datos de Scikit-learn en un conjunto de datos de Pandas?


106

¿Cómo convierto datos de un objeto Bunch de Scikit-learn a un Pandas DataFrame?

from sklearn.datasets import load_iris
import pandas as pd
data = load_iris()
print(type(data))
data1 = pd. # Is there a Pandas method to accomplish this?

Respuestas:


132

Manualmente, puede usar el pd.DataFrameconstructor, dando una matriz numérica ( data) y una lista de los nombres de las columnas ( columns). Para tener todo en un DataFrame, puede concatenar las características y el objetivo en una matriz numpy con np.c_[...](tenga en cuenta []):

import numpy as np
import pandas as pd
from sklearn.datasets import load_iris

# save load_iris() sklearn dataset to iris
# if you'd like to check dataset type use: type(load_iris())
# if you'd like to view list of attributes use: dir(load_iris())
iris = load_iris()

# np.c_ is the numpy concatenate function
# which is used to concat iris['data'] and iris['target'] arrays 
# for pandas column argument: concat iris['feature_names'] list
# and string list (in this case one string); you can make this anything you'd like..  
# the original dataset would probably call this ['Species']
data1 = pd.DataFrame(data= np.c_[iris['data'], iris['target']],
                     columns= iris['feature_names'] + ['target'])

3
¿Puedes agregar un pequeño texto para explicar este código? Esto es algo breve según nuestros estándares.
gung - Reincorporar a Monica

1
Algunos grupos tienen feature_names como un ndarray que romperá el parámetro de las columnas.

1
Falta la clave y los valores de "Especie" para el marco de datos.
mastash3ff

4
Este código no funcionó como está para mí. Para el parámetro de columnas, necesitaba pasar columnas = np.append (iris ['feature_names'], 'target). ¿Hice algo mal o esta respuesta necesita una edición?
Josh Davis

2
Esto no funciona para todos los conjuntos de datos, como load_boston(). Esta respuesta funciona de manera más general: stackoverflow.com/a/46379878/1840471
Max Ghenis


55

La solución de TOMDLt no es lo suficientemente genérica para todos los conjuntos de datos de scikit-learn. Por ejemplo, no funciona para el conjunto de datos de vivienda de Boston. Propongo una solución diferente, más universal. No es necesario usar numpy también.

from sklearn import datasets
import pandas as pd

boston_data = datasets.load_boston()
df_boston = pd.DataFrame(boston_data.data,columns=boston_data.feature_names)
df_boston['target'] = pd.Series(boston_data.target)
df_boston.head()

Como función general:

def sklearn_to_df(sklearn_dataset):
    df = pd.DataFrame(sklearn_dataset.data, columns=sklearn_dataset.feature_names)
    df['target'] = pd.Series(sklearn_dataset.target)
    return df

df_boston = sklearn_to_df(datasets.load_boston())

10

Solo como una alternativa que podría entender mucho más fácilmente:

data = load_iris()
df = pd.DataFrame(data['data'], columns=data['feature_names'])
df['target'] = data['target']
df.head()

Básicamente, en lugar de concatenar desde el principio, simplemente cree un marco de datos con la matriz de características y luego agregue la columna de destino con datos ['whatvername'] y obtenga los valores de destino del conjunto de datos


9

Me tomó 2 horas resolver esto

import numpy as np
import pandas as pd
from sklearn.datasets import load_iris

iris = load_iris()
##iris.keys()


df= pd.DataFrame(data= np.c_[iris['data'], iris['target']],
                 columns= iris['feature_names'] + ['target'])

df['species'] = pd.Categorical.from_codes(iris.target, iris.target_names)

Recupera la especie de mis pandas


7

De lo contrario, use conjuntos de datos de seaborn que son marcos de datos reales de pandas:

import seaborn
iris = seaborn.load_dataset("iris")
type(iris)
# <class 'pandas.core.frame.DataFrame'>

Compare con los conjuntos de datos de scikit learn:

from sklearn import datasets
iris = datasets.load_iris()
type(iris)
# <class 'sklearn.utils.Bunch'>
dir(iris)
# ['DESCR', 'data', 'feature_names', 'filename', 'target', 'target_names']

4

Esto funciona para mi.

dataFrame = pd.dataFrame(data = np.c_[ [iris['data'],iris['target'] ],
columns=iris['feature_names'].tolist() + ['target'])

3

Otra forma de combinar características y variables de destino puede ser usando np.column_stack( detalles )

import numpy as np
import pandas as pd
from sklearn.datasets import load_iris

data = load_iris()
df = pd.DataFrame(np.column_stack((data.data, data.target)), columns = data.feature_names+['target'])
print(df.head())

Resultado:

   sepal length (cm)  sepal width (cm)  petal length (cm)  petal width (cm)     target
0                5.1               3.5                1.4               0.2     0.0
1                4.9               3.0                1.4               0.2     0.0 
2                4.7               3.2                1.3               0.2     0.0 
3                4.6               3.1                1.5               0.2     0.0
4                5.0               3.6                1.4               0.2     0.0

Si necesita la etiqueta de cadena para el target, entonces se puede utilizar replacemediante la conversión target_namesa dictionaryy añadir una nueva columna:

df['label'] = df.target.replace(dict(enumerate(data.target_names)))
print(df.head())

Resultado:

   sepal length (cm)  sepal width (cm)  petal length (cm)  petal width (cm)     target  label 
0                5.1               3.5                1.4               0.2     0.0     setosa
1                4.9               3.0                1.4               0.2     0.0     setosa
2                4.7               3.2                1.3               0.2     0.0     setosa
3                4.6               3.1                1.5               0.2     0.0     setosa
4                5.0               3.6                1.4               0.2     0.0     setosa

2

Básicamente, lo que necesita son los "datos", y los tiene en el grupo de scikit, ahora solo necesita el "objetivo" (predicción) que también está en el grupo.

Así que solo necesito combinar estos dos para completar los datos

  data_df = pd.DataFrame(cancer.data,columns=cancer.feature_names)
  target_df = pd.DataFrame(cancer.target,columns=['target'])

  final_df = data_df.join(target_df)

2

A partir de la versión 0.23, puede devolver directamente un DataFrame usando el as_frameargumento. Por ejemplo, cargando el conjunto de datos de iris:

from sklearn.datasets import load_iris
iris = load_iris(as_frame=True)
df = iris.data

Según tengo entendido, al utilizar las notas de la versión provisional , esto funciona para los conjuntos de datos de cáncer de mama, diabetes, dígitos, iris, linnerud, vino y california_houses.


2

Actualización: 2020

Puede usar el parámetro as_frame=Truepara obtener marcos de datos de pandas.

Si el parámetro as_frame está disponible (por ejemplo, load_iris)

from sklearn import datasets
X,y = datasets.load_iris(return_X_y=True) # numpy arrays

dic_data = datasets.load_iris(as_frame=True)
print(dic_data.keys())

df = dic_data['frame'] # pandas dataframe data + target
df_X = dic_data['data'] # pandas dataframe data only
ser_y = dic_data['target'] # pandas series target only
dic_data['target_names'] # numpy array

Si el parámetro as_frame NO está disponible (por ejemplo, load_boston)

from sklearn import datasets

fnames = [ i for i in dir(datasets) if 'load_' in i]
print(fnames)

fname = 'load_boston'
loader = getattr(datasets,fname)()
df = pd.DataFrame(loader['data'],columns= loader['feature_names'])
df['target'] = loader['target']
df.head(2)

1

Trabajando con la mejor respuesta y abordando mi comentario, aquí hay una función para la conversión

def bunch_to_dataframe(bunch):
  fnames = bunch.feature_names
  features = fnames.tolist() if isinstance(fnames, np.ndarray) else fnames
  features += ['target']
  return pd.DataFrame(data= np.c_[bunch['data'], bunch['target']],
                 columns=features)

1

Cualquiera que sea la respuesta de TomDLT, puede que no funcione para algunos de ustedes porque

data1 = pd.DataFrame(data= np.c_[iris['data'], iris['target']],
                 columns= iris['feature_names'] + ['target'])

porque iris ['feature_names'] te devuelve una matriz numerosa. En la matriz numpy no puede agregar una matriz y una lista ['objetivo'] con solo + operador. Por lo tanto, primero debe convertirlo en una lista y luego agregarlo.

Tu puedes hacer

data1 = pd.DataFrame(data= np.c_[iris['data'], iris['target']],
                 columns= list(iris['feature_names']) + ['target'])

Esto funcionará bien aunque ...


0

Puede que haya una forma mejor, pero esto es lo que hice en el pasado y funciona bastante bien:

items = data.items()                          #Gets all the data from this Bunch - a huge list
mydata = pd.DataFrame(items[1][1])            #Gets the Attributes
mydata[len(mydata.columns)] = items[2][1]     #Adds a column for the Target Variable
mydata.columns = items[-1][1] + [items[2][0]] #Gets the column names and updates the dataframe

Ahora mydata tendrá todo lo que necesita: atributos, variables de destino y nombres de columnas


1
La solución de TomDLT es muy superior a lo que sugiero anteriormente. Hace lo mismo pero es muy elegante y fácil de entender. ¡Usa eso!
HakunaMaData

mydata = pd.DataFrame(items[1][1])lanzamientosTypeError: 'dict_items' object does not support indexing
Muestras de SANBI

0

Este fragmento es solo azúcar sintáctico construido sobre lo que TomDLT y rolyat ya han contribuido y explicado. Las únicas diferencias serían que load_irisdevolverán una tupla en lugar de un diccionario y los nombres de las columnas se enumerarán.

df = pd.DataFrame(np.c_[load_iris(return_X_y=True)])

Gracias por este fragmento de código, que puede proporcionar ayuda inmediata y limitada. Una explicación adecuada mejoraría enormemente su valor a largo plazo al mostrar por qué es una buena solución al problema y lo haría más útil para futuros lectores con otras preguntas similares. Por favor, editar su respuesta a añadir un poco de explicación, incluyendo los supuestos realizados.
Adiós StackExchange

0
import pandas as pd
from sklearn.datasets import load_iris
iris = load_iris()
X = iris['data']
y = iris['target']
iris_df = pd.DataFrame(X, columns = iris['feature_names'])
iris_df.head()

0

Una de las mejores formas:

data = pd.DataFrame(digits.data)

Digits es el dataframe sklearn y lo convertí en un DataFrame de pandas


0

Tomé un par de ideas de sus respuestas y no sé cómo hacerlo más corto :)

import pandas as pd
from sklearn.datasets import load_iris
iris = load_iris()
df = pd.DataFrame(iris.data, columns=iris['feature_names'])
df['target'] = iris['target']

Esto le da un Pandas DataFrame con feature_names más target como columnas y RangeIndex (start = 0, stop = len (df), step = 1). Me gustaría tener un código más corto donde pueda agregar 'objetivo' directamente.


0

La API es un poco más limpia que las respuestas sugeridas. Aquí, use as_framey asegúrese de incluir una columna de respuesta también.

import pandas as pd
from sklearn.datasets import load_wine

features, target = load_wine(as_frame=True).data, load_wine(as_frame=True).target
df = features
df['target'] = target

df.head(2)

0

Aquí hay otro ejemplo de método integrado que puede resultar útil.

from sklearn.datasets import load_iris
iris_X, iris_y = load_iris(return_X_y=True, as_frame=True)
type(iris_X), type(iris_y)

Los datos iris_X se importan como pandas DataFrame y el objetivo iris_y se importan como pandas Series.


0
from sklearn.datasets import load_iris
import pandas as pd

iris_dataset = load_iris()

datasets = pd.DataFrame(iris_dataset['data'], columns = 
           iris_dataset['feature_names'])
target_val = pd.Series(iris_dataset['target'], name = 
            'target_values')

species = []
for val in target_val:
    if val == 0:
        species.append('iris-setosa')
    if val == 1:
        species.append('iris-versicolor')
    if val == 2:
        species.append('iris-virginica')
species = pd.Series(species)

datasets['target'] = target_val
datasets['target_name'] = species
datasets.head()
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.