Estoy tratando de obtener un nuevo conjunto de datos o cambiar el valor de las columnas del conjunto de datos actual a sus valores únicos. Aquí hay un ejemplo de lo que estoy tratando de obtener:
AB ----- 0| 1 1 1| 2 5 2| 1 5 3| 7 9 4| 7 9 5| 8 9 Wanted Result Not Wanted Result ABAB ----- ----- 0| 1 1 0| 1 1 1| 2 5 1| 2 5 2| 7 9 2| 3| 8 3| 7 9 4| 5| 8Realmente no me importa el índice, pero parece ser el problema. Mi código hasta ahora es bastante simple, probé 2 enfoques, 1 con un nuevo marco de datos y otro sin él.
#With New DataFrame def UniqueResults(dataframe): df = pd.DataFrame() for col in dataframe: S=pd.Series(dataframe[col].unique()) df[col]=S.values return df #Without new DataFrame def UniqueResults(dataframe): for col in dataframe: dataframe[col]=dataframe[col].unique() return dataframeTengo el error "La longitud de los valores no coincide con la longitud del índice" en ambas ocasiones.
El error aparece cuando intenta asignar una lista de matrices numpy de diferente longitud a un marco de datos, y se puede reproducir de la siguiente manera:
Un marco de datos de cuatro filas:
df = pd.DataFrame({'A': [1,2,3,4]})Ahora tratando de asignarle una lista/matriz de dos elementos:
df['B'] = [3,4] # or df['B'] = np.array([3,4])Ambos errores fuera:
ValueError: la longitud de los valores no coincide con la longitud del índice
Porque el marco de datos tiene cuatro filas, pero la lista y la matriz solo tienen dos elementos.
Solución alternativa (use con precaución): convierta la lista/matriz en una Serie pandas, y luego, cuando realice la asignación, el índice faltante en la Serie se llenará con NaN :
df['B'] = pd.Series([3,4]) df # AB #0 1 3.0 #1 2 4.0 #2 3 NaN # NaN because the value at index 2 and 3 doesn't exist in the Series #3 4 NaNPara su problema específico, si no le importa el índice o la correspondencia de valores entre columnas, puede restablecer el índice para cada columna después de eliminar los duplicados:
df.apply(lambda col: col.drop_duplicates().reset_index(drop=True)) # AB #0 1 1.0 #1 2 5.0 #2 7 9.0 #3 8 NaNUna forma de solucionar este problema es mantener los valores únicos en una lista y usar itertools.zip_longest para transponer los datos y pasarlos al constructor de DataFrame:
from itertools import zip_longest def UniqueResults(dataframe): tmp = [dataframe[col].unique() for col in dataframe] return pd.DataFrame(zip_longest(*tmp), columns=dataframe.columns) out = UniqueResults(df)Producción:
AB 0 1 1.0 1 2 5.0 2 7 9.0 3 8 NaNAl menos para pequeños DataFrames, esto parece ser más rápido (por ejemplo, en la muestra de OP):
%timeit out = df.apply(lambda col: col.drop_duplicates().reset_index(drop=True)) 1.27 ms ± 50.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each) %timeit x = UniqueResults(df) 426 µs ± 24.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)