suelte las filas de objetos que no sean json de la columna del dataframe de Python

Tengo un dataframe tal que la columna contiene tanto objetos json como cadenas. Quiero deshacerme de las filas que no contienen objetos json.

A continuación se muestra cómo se ve mi dataframe:

import pandas as pd df = pd.DataFrame({'A': ["hello","world",{"a":5,"b":6,"c":8},"usa","india",{"a":9,"b":10,"c":11}]}) print(df) 

¿Cómo debo eliminar las filas que contienen solo cadenas, de modo que después de eliminarlas, puedo aplicar a esta columna a continuación para convertir el objeto json en columnas separadas del dataframe?

 from pandas.io.json import json_normalize df = json_normalize(df['A']) print(df) 

Creo que preferiría usar un control de isinstance :

 In [11]: df.loc[df.A.apply(lambda d: isinstance(d, dict))] Out[11]: A 2 {'a': 5, 'b': 6, 'c': 8} 5 {'d': 9, 'e': 10, 'f': 11} 

Si quieres incluir números también, puedes hacer:

 In [12]: df.loc[df.A.apply(lambda d: isinstance(d, (dict, np.number)))] Out[12]: A 2 {'a': 5, 'b': 6, 'c': 8} 5 {'d': 9, 'e': 10, 'f': 11} 

Ajústalo a los tipos que quieras incluir …


El último paso, json_normalize toma una lista de objetos json, por el motivo que sea que una Serie no es buena (y le da el KeyError), puede hacer que esta sea una lista y estará lista:

 In [21]: df1 = df.loc[df.A.apply(lambda d: isinstance(d, (dict, np.number)))] In [22]: json_normalize(list(df1["A"])) Out[22]: abcdef 0 5.0 6.0 8.0 NaN NaN NaN 1 NaN NaN NaN 9.0 10.0 11.0 
 df[df.applymap(np.isreal).sum(1).gt(0)] Out[794]: A 2 {'a': 5, 'b': 6, 'c': 8} 5 {'d': 9, 'e': 10, 'f': 11} 

Si quieres una solución fea que también funciona … aquí hay una función que creé que encuentra columnas que solo contienen cadenas y devuelve el df menos esas filas. (dado que su df solo tiene una columna, solo tendrá que contener el dataframe que contiene 1 columna con todos los dictados). Luego, a partir de ahí, querrá usar df = json_normalize(df['A'].values) lugar de solo df = json_normalize(df['A']) .

Para una sola columna de datos …

 import pandas as pd import numpy as np from pandas.io.json import json_normalize def delete_strings(df): nrows = df.shape[0] rows_to_keep = [] for row in np.arange(nrows): if type(df.iloc[row,0]) == dict: rows_to_keep.append(row) #add the row number to list of rows #to keep if the row contains a dict return df.iloc[rows_to_keep,0] #return only rows with dicts df = pd.DataFrame({'A': ["hello","world",{"a":5,"b":6,"c":8},"usa","india", {"a":9,"b":10,"c":11}]}) df = delete_strings(df) df = json_normalize(df['A'].values) print(df) #0 {'a': 5, 'b': 6, 'c': 8} #1 {'a': 9, 'b': 10, 'c': 11} 

Para un df de varias columnas (también funciona con una sola columna df):

 def delete_rows_of_strings(df): rows = df.shape[0] #of rows in df cols = df.shape[1] #of coluns in df rows_to_keep = [] #list to track rows to keep for row in np.arange(rows): #for every row in the dataframe #num_string will count the number of strings in the row num_string = 0 for col in np.arange(cols): #for each column in the row... #if the value is a string, add one to num_string if type(df.iloc[row,col]) == str: num_string += 1 #if num_string, the number of strings in the column, #isn't equal to the number of columns in the row... if num_string != cols: #...add that row number to the list of rows to keep rows_to_keep.append(row) #return the df with rows containing at least one non string return(df.iloc[rows_to_keep,:]) df = pd.DataFrame({'A': ["hello","world",{"a":5,"b":6,"c":8},"usa","india"], 'B' : ['hi',{"a":5,"b":6,"c":8},'sup','america','china']}) # AB #0 hello hi #1 world {'a': 5, 'b': 6, 'c': 8} #2 {'a': 5, 'b': 6, 'c': 8} sup print(delete_rows_of_strings(df)) # AB #1 world {'a': 5, 'b': 6, 'c': 8} #2 {'a': 5, 'b': 6, 'c': 8} sup