He cargado en un csv que se ve así

  Unnamed: 0  Unnamed: 1  Unnamed: 2  Unnamed: 3
        Date      Price     Quantity     Colour
        2019        45         56         Blue
        2019        34         65         Red
        Date      Price     Quantity     Size
        2019        12         32         Large
        2019        45         11         Small
        Date      Price     Country     
        2019        12         UK        
        2019        45         US         

Quería convertir esto en un marco de datos completo, por lo que la salida esperada es esta;

    Date      Price     Quantity     Colour  Size  Country
    2019        45         56         Blue   NaN    NaN    
    2019        34         65         Red    NaN    NaN    
    2019        12         32        NaN    Large   NaN    
    2019        45         11        NaN    Small   NaN    
    2019        12         32        NaN    NaN     UK
    2019        45         11        NaN    NaN     US

La palabra Fecha en la primera columna siempre dividirá las tablas.

1
fred.schwartz 6 feb. 2020 a las 15:53

2 respuestas

La mejor respuesta

Si es posible utilizar la cadena Date para distinguir cada grupo, compare y agregue Series.cumsum, pase a groupby y en la función personalizada cree columnas en la primera fila y elimínelas por DataFrame.iloc:

g = df.iloc[:, 0].eq('Date').cumsum()

def f(x):
    x.columns = x.iloc[0]
    return x.iloc[1:].dropna(how='all', axis=1)

df = df.groupby(g).apply(f).reset_index(drop=True)
print (df)
   Date Price Quantity Colour   Size
0  2019    45       56   Blue    NaN
1  2019    34       65    Red    NaN
2  2019    12       32    NaN  Large
3  2019    45       11    NaN  Small
4
jezrael 6 feb. 2020 a las 13:09

Usaría np.arange para usar DataFrame.groupby y pd.concat:

new_df = (pd.concat([pd.DataFrame(columns = group.iloc[0],
                                  index =group.index[1:],
                                  data = group.iloc[1:].values)
                    for i,group in df.groupby(np.arange(len(df))//3)],sort = False)
            .dropna(how = 'all',axis = 1))
print(new_df)
   Date Price Quantity Colour   Size Country
1  2019    45       56   Blue    NaN     NaN
2  2019    34       65    Red    NaN     NaN
4  2019    12       32    NaN  Large     NaN
5  2019    45       11    NaN  Small     NaN
7  2019    12      NaN    NaN    NaN      UK
8  2019    45      NaN    NaN    NaN      US

Si la longitud de cada cuadro para concatenar no es la misma, entonces usaría Series.cumsum

new_df = (pd.concat([pd.DataFrame(columns = group.iloc[0],
                                  index =group.index[1:],
                                  data = group.iloc[1:].values)
                    for i,group in df.groupby(df.iloc[:,0].eq('date').cumsum())],sort = False)
            .dropna(how = 'all',axis = 1))
print(new_df)
0  Date  Price  Quantity Colour
1  2019     45        56   Blue
2  2019     34        65    Red
3  Date  Price  Quantity   Size
4  2019     12        32  Large
5  2019     45        11  Small
6  Date  Price   Country    NaN
7  2019     12        UK    NaN
8  2019     45        US    NaN
1
ansev 6 feb. 2020 a las 13:27