pie exportar excelwriter example con chart pandas

exportar - pandas plot pie chart



Cómo crear una estructura de datos retrasada usando el marco de datos pandas (6)

Como se mencionó, podría valer la pena mirar las funciones rolling_ , lo que significará que no tendrá tantas copias alrededor.

Una solución es concat serie shifted para hacer un DataFrame:

In [11]: pd.concat([s, s.shift(), s.shift(2)], axis=1) Out[11]: 0 1 2 1 5 NaN NaN 2 4 5 NaN 3 3 4 5 4 2 3 4 5 1 2 3 In [12]: pd.concat([s, s.shift(), s.shift(2)], axis=1).dropna() Out[12]: 0 1 2 3 3 4 5 4 2 3 4 5 1 2 3

Trabajar en esto será más eficiente que en las listas ...

Ejemplo

s=pd.Series([5,4,3,2,1], index=[1,2,3,4,5]) print s 1 5 2 4 3 3 4 2 5 1

¿Hay una manera eficiente de crear una serie. por ejemplo, que contiene en cada fila los valores retrasados ​​(en este ejemplo hasta el retraso 2)

3 [3, 4, 5] 4 [2, 3, 4] 5 [1, 2, 3]

Esto corresponde a s = pd.Serie ([[3,4,5], [2,3,4], [1,2,3]], índice = [3,4,5])

¿Cómo se puede hacer esto de manera eficiente para los marcos de datos con muchas series temporales que son muy largas?

Gracias

Editado después de ver las respuestas.

ok, al final implementé esta función:

def buildLaggedFeatures(s,lag=2,dropna=True): '''''' Builds a new DataFrame to facilitate regressing over all possible lagged features '''''' if type(s) is pd.DataFrame: new_dict={} for col_name in s: new_dict[col_name]=s[col_name] # create lagged Series for l in range(1,lag+1): new_dict[''%s_lag%d'' %(col_name,l)]=s[col_name].shift(l) res=pd.DataFrame(new_dict,index=s.index) elif type(s) is pd.Series: the_range=range(lag+1) res=pd.concat([s.shift(i) for i in the_range],axis=1) res.columns=[''lag_%d'' %i for i in the_range] else: print ''Only works for DataFrame or Series'' return None if dropna: return res.dropna() else: return res

produce los resultados deseados y gestiona la denominación de las columnas en el DataFrame resultante.

Para una serie como entrada:

s=pd.Series([5,4,3,2,1], index=[1,2,3,4,5]) res=buildLaggedFeatures(s,lag=2,dropna=False) lag_0 lag_1 lag_2 1 5 NaN NaN 2 4 5 NaN 3 3 4 5 4 2 3 4 5 1 2 3

y para un DataFrame como entrada:

s2=s=pd.DataFrame({''a'':[5,4,3,2,1], ''b'':[50,40,30,20,10]},index=[1,2,3,4,5]) res2=buildLaggedFeatures(s2,lag=2,dropna=True) a a_lag1 a_lag2 b b_lag1 b_lag2 3 3 4 5 30 40 50 4 2 3 4 20 30 40 5 1 2 3 10 20 30


Me gusta poner los números de retraso en las columnas haciendo que las columnas sean un MultiIndex . De esta manera, se conservan los nombres de las columnas.

Aquí hay un ejemplo del resultado:

# Setup indx = pd.Index([1, 2, 3, 4, 5], name=''time'') s=pd.Series( [5, 4, 3, 2, 1], index=indx, name=''population'') shift_timeseries_by_lags(pd.DataFrame(s), [0, 1, 2])

Resultado: un multiindex DataFrame con dos etiquetas de columna: el original ("población") y uno nuevo ("retraso"):

Solución : Al igual que en la solución aceptada, usamos DataFrame.shift y luego pandas.concat .

def shift_timeseries_by_lags(df, lags, lag_label=''lag''): return pd.concat([ shift_timeseries_and_create_multiindex_column(df, lag, lag_label=lag_label) for lag in lags], axis=1) def shift_timeseries_and_create_multiindex_column( dataframe, lag, lag_label=''lag''): return (dataframe.shift(lag) .pipe(append_level_to_columns_of_dataframe, lag, lag_label))

Me gustaría que hubiera una manera fácil de agregar una lista de etiquetas a las columnas existentes. Aquí está mi solución.

def append_level_to_columns_of_dataframe( dataframe, new_level, name_of_new_level, inplace=False): """Given a (possibly MultiIndex) DataFrame, append labels to the column labels and assign this new level a name. Parameters ---------- dataframe : a pandas DataFrame with an Index or MultiIndex columns new_level : scalar, or arraylike of length equal to the number of columns in `dataframe` The labels to put on the columns. If scalar, it is broadcast into a list of length equal to the number of columns in `dataframe`. name_of_new_level : str The label to give the new level. inplace : bool, optional, default: False Whether to modify `dataframe` in place or to return a copy that is modified. Returns ------- dataframe_with_new_columns : pandas DataFrame with MultiIndex columns The original `dataframe` with new columns that have the given `level` appended to each column label. """ old_columns = dataframe.columns if not hasattr(new_level, ''__len__'') or isinstance(new_level, str): new_level = [new_level] * dataframe.shape[1] if isinstance(dataframe.columns, pd.MultiIndex): new_columns = pd.MultiIndex.from_arrays( old_columns.levels + [new_level], names=(old_columns.names + [name_of_new_level])) elif isinstance(dataframe.columns, pd.Index): new_columns = pd.MultiIndex.from_arrays( [old_columns] + [new_level], names=([old_columns.name] + [name_of_new_level])) if inplace: dataframe.columns = new_columns return dataframe else: copy_dataframe = dataframe.copy() copy_dataframe.columns = new_columns return copy_dataframe

Actualización : aprendí de esta solución otra forma de poner un nuevo nivel en una columna, lo que hace que no sea necesario usar append_level_to_columns_of_dataframe :

def shift_timeseries_by_lags_v2(df, lags, lag_label=''lag''): return pd.concat({ ''{lag_label}_{lag_number}''.format(lag_label=lag_label, lag_number=lag): df.shift(lag) for lag in lags}, axis=1)

Aquí está el resultado de shift_timeseries_by_lags_v2(pd.DataFrame(s), [0, 1, 2]) :


Para un df de marco de datos con el retraso que se aplicará en ''nombre de columna'', puede usar la función de cambio.

df[''lag1'']=df[''col name''].shift(1) df[''lag2'']=df[''col name''].shift(2)


Para varios retrasos (muchos de ellos), esto podría ser más compacto:

df=pd.DataFrame({''year'': range(2000, 2010), ''gdp'': [234, 253, 256, 267, 272, 273, 271, 275, 280, 282]}) df.join(pd.DataFrame({''gdp_'' + str(lag): df[''gdp''].shift(lag) for lag in range(1,4)}))


Puedes hacer lo siguiente:

s=pd.Series([5,4,3,2,1], index=[1,2,3,4,5]) res = pd.DataFrame(index = s.index) for l in range(3): res[l] = s.shift(l) print res.ix[3:,:].as_matrix()

Produce:

array([[ 3., 4., 5.], [ 2., 3., 4.], [ 1., 2., 3.]])

que espero que sea muy cercano a lo que realmente quieres.


Solución muy simple usando pandas DataFrame:

number_lags = 3 df = pd.DataFrame(data={''vals'':[5,4,3,2,1]}) for lag in xrange(1, number_lags + 1): df[''lag_'' + str(lag)] = df.vals.shift(lag) #if you want numpy arrays with no null values: df.dropna().values for numpy arrays