Подтвердить что ты не робот

Как объединить серию и DataFrame

Если вы пришли сюда в поисках информации о том, как объединить DataFrame и Series в индексе, посмотрите этот ответ.

Первоначальным намерением OP было задание вопроса о том, как назначить элементы серии в виде столбцов другому DataFrame. Если вам интересно узнать ответ на этот вопрос, посмотрите на принятый ответ EdChum.


Лучшее, что я могу придумать, это

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

Кто-нибудь может предложить лучший синтаксис/более быстрый метод?

Мои попытки:

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

а также

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

РЕДАКТИРОВАТЬ Первые два опубликованных ответа выделили проблему с моим вопросом, поэтому, пожалуйста, используйте следующее для построения df:

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

с окончательным результатом

    a  b  s1  s2
3 NaN  4   5   6
5   2  5   5   6
6   3  6   5   6
4b9b3361

Ответ 1

Вы можете построить блок данных из серии и затем объединиться с файловой рамкой. Поэтому вы указываете данные как значения, но умножаете их на длину, устанавливаете столбцы в индекс и устанавливаете параметры для left_index и right_index в True:

In [27]:

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

РЕДАКТИРОВАТЬ для ситуации, когда вы хотите, чтобы индекс вашего построенного df из серии использовал индекс df, вы можете сделать следующее:

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

Это предполагает, что индексы соответствуют длине.

Ответ 2

В настоящее время вы можете просто преобразовать Series в DataFrame с помощью to_frame(). Итак (при присоединении по индексу):

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

Начиная с v0.24.0, вы можете объединять DataFrame и Series, пока Series назван.

df.merge(s.rename('new'), left_index=True, right_index=True)

Ответ 3

Здесь один из способов:

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

Чтобы сломать то, что здесь происходит...

pd.DataFrame(s).T создает однострочный DataFrame из s который выглядит следующим образом:

   s1  s2
0   5   6

Затем join объединяет этот новый кадр с помощью df:

   a  b  s1  s2
0  1  3   5   6
1  2  4 NaN NaN

Наконец, значения NaN в индексе 1 заполняются предыдущими значениями в столбце с использованием fillna с fillna forward-fill (ffill):

   a  b  s1  s2
0  1  3   5   6
1  2  4   5   6

Чтобы избежать использования fillna, можно использовать pd.concat для повторения строк DataFrame, созданных из s. В этом случае общее решение:

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

Вот еще одно решение для решения проблемы индексации, поставленной в отредактированном вопросе:

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

s преобразуется в DataFrame путем повторения значений и изменения их формы (с указанием порядка 'Fortran'), а также передачи соответствующих имен столбцов и индекса. Этот новый DataFrame затем присоединяется к df.

Ответ 4

Текущий с v0.23.4 - альтернативы для merge

Объединение DataFrame и Series

Настроить

df
      a  b
s1  NaN  4
s2  2.0  5
s3  3.0  6

s

s1    5
s2    6
dtype: int64

pd.concat
Если вы хотите объединить DataFrame или Series с индексом, вы можете использовать pd.concat, который принимает ряд:

pd.concat([df, s], axis=1, sort=False, join='inner')

      a  b  0
s1  NaN  4  5
s2  2.0  5  6

Который такой же как (но быстрее чем)

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

      a  b  0
s1  NaN  4  5
s2  2.0  5  6 

DataFrame.assign
Используйте assign, добавив шаг loc для индексации с пересечением индекса.

df2.assign(new=s).loc[(df.index & s.index).unique()]

Это также обрабатывает дубликаты в индексе (что concat не может).

df2 = df.copy()
df2.index = ['s1', 's2', 's1']
df2

      a  b
s1  NaN  4
s2  2.0  5
s1  3.0  6

df2.assign(new=s).loc[(df.index & s.index).unique()]
# Equivalent to 
# df.merge(s.to_frame(), left_index=True, right_index=True) 

      a  b  new
s1  NaN  4    5
s1  3.0  6    5
s2  2.0  5    6

Если индекс уникален, решение немного упрощается, отбросьте вызов unique:

df2.assign(new=s).loc[df.index & s.index]

Отвечая на вопрос ОП - df.assign, снова

df.assign(**s)

   a  b  s1  s2
0  1  3   5   6
1  2  4   5   6

а также,

     a  b  s1  s2
3  NaN  4   5   6
5  2.0  5   5   6
6  3.0  6   5   6

(Это работает на обоих примерах.)

Ответ 5

Если бы я мог предложить настроить ваши данные как это (автоиндексирование):

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

тогда вы можете настроить свои значения s1 и s2 таким образом (используя форму(), чтобы вернуть количество строк из df):

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

то нужный результат легко:

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

В качестве альтернативы просто добавьте новые значения в ваш dataframe df:

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

Оба возвращаются:

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

Если у вас есть другой список данных (а не только одно значение для применения), и вы знаете, что оно находится в той же последовательности, что и df, например:

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

то вы можете присоединить его так же:

df['s1']=s1

возвращает:

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

Ответ 6

Вы можете легко установить столбец pandas.DataFrame в константу. Эта константа может быть int, как в вашем примере. Если указанный вами столбец отсутствует в df, тогда pandas создаст новый столбец с указанным вами именем. Итак, после того, как ваш dataframe построен, (из вашего вопроса):

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

Вы можете просто запустить:

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

Вы можете написать цикл или понимание, чтобы он делал это для всех элементов в списке кортежей или ключей и значений в словаре в зависимости от того, как хранятся ваши реальные данные.