Como mesclar uma série e um DataFrame

Se você veio aqui procurando informações sobre como mesclar um DataFrame e uma Series no índice , veja esta resposta .

A intenção original do OP era perguntar como atribuir elementos de série como colunas a outro DataFrame . Se você está interessado em saber a resposta para isso, veja a resposta aceita pelo EdChum.


O melhor que posso encontrar é

 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] ab s1 s2 0 1 3 5 6 1 2 4 5 6 

Alguém pode sugerir melhor syntax / método mais rápido?

Minhas tentativas

 df.merge(s) AttributeError: 'Series' object has no attribute 'columns' 

e

 df.join(s) ValueError: Other Series must have a name 

EDIT As primeiras duas respostas postadas destacaram um problema com a minha pergunta, então por favor use o seguinte para construir o df :

 df = pd.DataFrame({'a':[np.nan, 2, 3], 'b':[4, 5, 6]}, index=[3, 5, 6]) 

com o resultado final

  ab s1 s2 3 NaN 4 5 6 5 2 5 5 6 6 3 6 5 6 

Você pode construir um dataframe da série e, em seguida, mesclar com o dataframe. Assim, você especifica os dados como os valores, mas os multiplica pelo comprimento, configura as colunas para o índice e define parâmetros para left_index e right_index para True:

 In [27]: df.merge(pd.DataFrame(data = [s.values] * len(s), columns = s.index), left_index=True, right_index=True) Out[27]: ab s1 s2 0 1 3 5 6 1 2 4 5 6 

EDIT para a situação em que você quer que o índice de seu df construído da série use o índice do df, então você pode fazer o seguinte:

 df.merge(pd.DataFrame(data = [s.values] * len(df), columns = s.index, index=df.index), left_index=True, right_index=True) 

Isso pressupõe que os índices correspondam ao comprimento.

Atualizar
A partir da v0.24.0, você pode mesclar DataFrame e Series, desde que a série seja nomeada.

 df.merge(s.rename('new'), left_index=True, right_index=True) # If series is already named, # df.merge(s, left_index=True, right_index=True) 

Hoje em dia, você pode simplesmente converter a série em um DataFrame com to_frame () . Então (se juntando no índice):

 df.merge(s.to_frame(), left_index=True, right_index=True) 

Aqui está um jeito:

 df.join(pd.DataFrame(s).T).fillna(method='ffill') 

Para quebrar o que acontece aqui …

pd.DataFrame(s).T cria um DataFrame de uma linha de s que se parece com isto:

  s1 s2 0 5 6 

Em seguida, join concatena esse novo quadro com df :

  ab s1 s2 0 1 3 5 6 1 2 4 NaN NaN 

Por fim, os valores NaN no índice 1 são preenchidos com os valores anteriores na coluna usando fillna com o argumento forward-fill ( ffill ):

  ab s1 s2 0 1 3 5 6 1 2 4 5 6 

Para evitar o uso de fillna , é possível usar pd.concat para repetir as linhas do DataFrame construídas a partir de s . Nesse caso, a solução geral é:

 df.join(pd.concat([pd.DataFrame(s).T] * len(df), ignore_index=True)) 

Aqui está outra solução para resolver o desafio de indexação colocado na questão editada:

 df.join(pd.DataFrame(s.repeat(len(df)).values.reshape((len(df), -1), order='F'), columns=s.index, index=df.index)) 

s é transformado em um DataFrame, repetindo os valores e reformulando (especificando a ordem ‘Fortran’), e também passando os nomes e índices de coluna apropriados. Este novo DataFrame é então associado ao df .

Se eu pudesse sugerir a configuração de seus dataframes como este (auto-indexação):

 df = pd.DataFrame({'a':[np.nan, 1, 2], 'b':[4, 5, 6]}) 

então você pode configurar seus valores s1 e s2 assim (usando shape () para retornar o número de linhas de df):

 s = pd.DataFrame({'s1':[5]*df.shape[0], 's2':[6]*df.shape[0]}) 

então o resultado que você quer é fácil:

 display (df.merge(s, left_index=True, right_index=True)) 

Como alternativa, basta adicionar os novos valores ao seu dataframe df:

 df = pd.DataFrame({'a':[nan, 1, 2], 'b':[4, 5, 6]}) df['s1']=5 df['s2']=6 display(df) 

Ambos retornam:

  ab s1 s2 0 NaN 4 5 6 1 1.0 5 5 6 2 2.0 6 5 6 

Se você tem outra lista de dados (em vez de apenas um único valor para aplicar), e você sabe que está na mesma seqüência que df, por exemplo:

 s1=['a','b','c'] 

então você pode append isto da mesma maneira:

 df['s1']=s1 

retorna:

  ab s1 0 NaN 4 a 1 1.0 5 b 2 2.0 6 c 

Você pode facilmente definir uma coluna pandas.DataFrame como uma constante. Essa constante pode ser um int como no seu exemplo. Se a coluna que você especificar não estiver no df, os pandas criarão uma nova coluna com o nome que você especificar. Então, depois que seu dataframe for construído, (da sua pergunta):

 df = pd.DataFrame({'a':[np.nan, 2, 3], 'b':[4, 5, 6]}, index=[3, 5, 6]) 

Você pode apenas executar:

 df['s1'], df['s2'] = 5, 6 

Você pode escrever um loop ou compreensão para fazer isso para todos os elementos em uma lista de tuplas, ou chaves e valores em um dictionary, dependendo de como você tem seus dados reais armazenados.