Reconstruir pandas Dataframe
Soy bastante nuevo en Python. Tengo problemas para reconstruir un Dataframe defectuoso. Mi marco de datos se ve así:
df = pd.DataFrame({'col1': ['id 1', 'id 2', 'test 3', 'test 4'],
'col2': ['test 1', 'test 2',
'Number 6135', 'id 4'],
'col3': ['Number 12344', 'Number 21612','id 3','Number 1131']})
Como puede ver tengo las "id´s" en la primera, segunda y tercera col. Lo mismo para los otros valores.
Mi objetivo es tener un marco de datos en el que cada columna tenga solo los valores que comiencen con la misma subcadena como este ejemplo:
Ya intenté usar for Loops y if Statments para verificar si una determinada subcadena está en mi cadena. si eso es cierto, creo una nueva columna y escribo mi valor dentro de ella
for x in df['col1']:
if 'id' in x:
df['newCol']=x
Sé que este código nunca resolverá mi problema, tal vez haya alguna función pandas que pueda ayudarme a resolver este problema
Si algo no está claro, pregúnteme. Haré todo lo posible para explicar mi problema. Gracias de antemano por su ayuda y sea fácil conmigo :)
Respuestas
Puede utilizar sorted()con la función de tecla personalizada:
def key_fn(x):
if 'id' in x:
return 0
if 'test' in x:
return 1
if 'Number' in x:
return 2
return 3
df = df.apply(lambda x: pd.Series(sorted(x, key=key_fn)), axis=1)
df = df.rename(columns=lambda x: 'col{}'.format(x+1))
print(df)
Huellas dactilares:
col1 col2 col3
0 id 1 test 1 Number 12344
1 id 2 test 2 Number 21612
2 id 3 test 3 Number 6135
3 id 4 test 4 Number 1131
Otra versión, de los comentarios:
df = pd.DataFrame([sorted(l, key=key_fn) for l in df.values], columns=df.columns)
print(df)
Si es posible, simplifique la solución dividiendo los valores por el primer espacio en blanco:
df = (df.reset_index()
.melt('index')
.assign(new = lambda x: x['value'].str.split().str[0])
.pivot('index','new','value'))
print (df)
new Number id test
index
0 Number 12344 id 1 test 1
1 Number 21612 id 2 test 2
2 Number 6135 id 3 test 3
3 Number 1131 id 4 test 4
De lo contrario, puede usar Series.str.extract:
L = ['id','test','Number']
df = (df.reset_index()
.melt('index')
.assign(new = lambda x: x['value'].str.extract(f'({"|".join(L)})', expand=False))
.pivot('index','new','value'))
print (df)
new Number id test
index
0 Number 12344 id 1 test 1
1 Number 21612 id 2 test 2
2 Number 6135 id 3 test 3
3 Number 1131 id 4 test 4
Prueba esto:
s = df.melt()['value']
df_final = pd.DataFrame({x: s[s.str.startswith(x)].values
for x in s.str.split().str[0].unique()})
Out[27]:
id test Number
0 id 1 test 3 Number 6135
1 id 2 test 4 Number 12344
2 id 4 test 1 Number 21612
3 id 3 test 2 Number 1131
Primero puede derretir el marco de datos, luego usar numpy select para reordenar los nombres y finalmente pivotar :
(df.melt(ignore_index=False)
.assign(variable=lambda x: np.select([x.value.str.startswith("id"),
x.value.str.startswith("test"),
x.value.str.startswith("Number")],
["col1", "col2", "col3"]))
.reset_index()
.pivot("index", "variable", "value")
.rename_axis(columns=None, index=None))
col1 col2 col3
0 id 1 test 1 Number 12344
1 id 2 test 2 Number 21612
2 id 3 test 3 Number 6135
3 id 4 test 4 Number 1131