Si usted vino aquí en busca de información sobre cómo combinar una
DataFrame
ySeries
en el índice , por favor vaya a esta respuesta .La intención original del OP era preguntar cómo asignar elementos de serie como columnas a otro DataFrame . Si está interesado en conocer la respuesta a esto, mire la respuesta aceptada por EdChum.
Lo mejor que se me ocurre es
df = pd.DataFrame({'a':[1, 2], 'b':[3, 4]}) # see EDIT below
s = pd.Series({'s1':5, 's2':6})
for name in s.index:
df[name] = s[name]
a b s1 s2
0 1 3 5 6
1 2 4 5 6
¿Alguien puede sugerir una mejor sintaxis / un método más rápido?
Mis intentos:
df.merge(s)
AttributeError: 'Series' object has no attribute 'columns'
y
df.join(s)
ValueError: Other Series must have a name
EDITAR Las dos primeras respuestas publicadas destacaron un problema con mi pregunta, así que use lo siguiente para construir df
:
df = pd.DataFrame({'a':[np.nan, 2, 3], 'b':[4, 5, 6]}, index=[3, 5, 6])
con el resultado final
a b s1 s2
3 NaN 4 5 6
5 2 5 5 6
6 3 6 5 6
df
ys
, esta respuesta me devuelve un marco de datos vacío, no el resultado solicitado en la pregunta. No queremos hacer coincidir en el índice; queremos transmitir loss
valores a todas las filas dedf
.He aquí una forma:
df.join(pd.DataFrame(s).T).fillna(method='ffill')
Para analizar lo que sucede aquí ...
pd.DataFrame(s).T
crea un DataFrame de una filas
que se ve así:s1 s2 0 5 6
A continuación,
join
concatena este nuevo marco condf
:a b s1 s2 0 1 3 5 6 1 2 4 NaN NaN
Por último, los
NaN
valores en el índice 1 se rellenan con los valores anteriores en la columna usandofillna
elffill
argumento forward-fill ( ):a b s1 s2 0 1 3 5 6 1 2 4 5 6
Para evitar el uso
fillna
, es posible usarpd.concat
para repetir las filas del DataFrame construido a partir des
. En este caso, la solución general es:df.join(pd.concat([pd.DataFrame(s).T] * len(df), ignore_index=True))
Aquí hay otra solución para abordar el desafío de indexación planteado en la pregunta editada:
df.join(pd.DataFrame(s.repeat(len(df)).values.reshape((len(df), -1), order='F'), columns=s.index, index=df.index))
s
se transforma en un DataFrame repitiendo los valores y remodelando (especificando el orden 'Fortran'), y también pasando los nombres de columna y el índice apropiados. A continuación, se une este nuevo DataFramedf
.fuente
NaN
valores.index=[3, 5]
las nuevas columnas contienen nan después de su comando.2
debería serlen(df)
de aplicación general.Si pudiera sugerirle que configure sus marcos de datos como este (autoindexación):
df = pd.DataFrame({'a':[np.nan, 1, 2], 'b':[4, 5, 6]})
luego puede configurar sus valores s1 y s2 así (usando shape () para devolver el número de filas de df):
s = pd.DataFrame({'s1':[5]*df.shape[0], 's2':[6]*df.shape[0]})
entonces el resultado que desea es fácil:
display (df.merge(s, left_index=True, right_index=True))
Alternativamente, simplemente agregue los nuevos valores a su marco de datos df:
df = pd.DataFrame({'a':[nan, 1, 2], 'b':[4, 5, 6]}) df['s1']=5 df['s2']=6 display(df)
Ambos regresan:
a b s1 s2 0 NaN 4 5 6 1 1.0 5 5 6 2 2.0 6 5 6
Si tiene otra lista de datos (en lugar de un solo valor para aplicar), y sabe que está en la misma secuencia que df, por ejemplo:
s1=['a','b','c']
entonces puedes adjuntar esto de la misma manera:
df['s1']=s1
devoluciones:
a b s1 0 NaN 4 a 1 1.0 5 b 2 2.0 6 c
fuente
Puede establecer fácilmente una columna pandas.DataFrame en una constante. Esta constante puede ser un int como en su ejemplo. Si la columna que especifica no está en el df, los pandas crearán una nueva columna con el nombre que especifique. Entonces, después de que se construya su marco de datos, (de su pregunta):
df = pd.DataFrame({'a':[np.nan, 2, 3], 'b':[4, 5, 6]}, index=[3, 5, 6])
Puedes simplemente ejecutar:
df['s1'], df['s2'] = 5, 6
Puede escribir un bucle o comprensión para que haga esto para todos los elementos en una lista de tuplas, o claves y valores en un diccionario, dependiendo de cómo tenga almacenados sus datos reales.
fuente
Si
df
es un,pandas.DataFrame
entoncesdf['new_col']= Series list_object of length len(df)
agregará el objeto de lista o Serie como una columna nombrada'new_col'
.df['new_col']= scalar
(como 5 o 6 en su caso) también funciona y es equivalente adf['new_col']= [scalar]*len(df)
Entonces, un código de dos líneas sirve para el propósito:
df = pd.DataFrame({'a':[1, 2], 'b':[3, 4]}) s = pd.Series({'s1':5, 's2':6}) for x in s.index: df[x] = s[x] Output: a b s1 s2 0 1 3 5 6 1 2 4 5 6
fuente