如何合并 Series 和 DataFrame

如果你来这里寻找关于 < em > 如何 merge a DataFrame and Series on the index, please look at this 回答

OP 的初衷是询问 < em > 如何分配系列元素 as columns to another DataFrame. If you are interested in knowing the 回答这个问题,看看 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

Can anybody suggest better syntax / faster method?

我的尝试:

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
216854 次浏览

您可以从该系列中构建一个数据框架,然后与该数据框架合并。 因此,您可以将数据指定为值,但将它们乘以长度,将列设置为索引,并将 left_indexright_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)

这里假设索引与长度匹配。

Here's one way:

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

为了打破这里发生的一切。

pd.DataFrame(s).Ts创建一行 DataFrame,如下所示:

   s1  s2
0   5   6

接下来,join将这个新帧与 df连接起来:

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

最后,使用带有 forward-fill (ffill)参数的 fillna,将索引1处的 NaN值填充为列中的前一个值:

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

为了避免使用 fillna,可以使用 pd.concat重复从 s构造的 DataFrame 的行。在这种情况下,一般的解决方案是:

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))

通过重复值和重新形状(指定‘ Fortran’顺序) ,并传入适当的列名和索引,将 s转换为 DataFrame。然后将这个新的 DataFrame 连接到 df

更新
从 v0.24.0开始,只要 Series 被命名,就可以在 DataFrame 和 Series 上进行合并。

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)

现在,你可以简单地用 To _ frame ()将 Series 转换成 DataFrame。所以(如果加入索引) :

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

如果我可以建议像这样设置你的数据框架(自动索引) :

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

然后可以这样设置 s1和 s2值(使用 form ()返回 df 中的行数) :

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

那么你想要的结果很简单:

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

或者,只需将新值添加到数据框 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

If you have another list of data (instead of just a single value to apply), and you know it is in the same sequence as df, eg:

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

然后你可以用同样的方法把这个连接起来:

df['s1']=s1

报税表:

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

你可以很容易地设置一个熊猫。将 DataFrame 列设置为常数。这个常量可以是一个 int,就像你的例子一样。如果您指定的列不在 df 中,那么“熊猫”将创建一个具有您指定名称的新列。因此,在构建数据框架之后,(根据您的问题) :

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

你可以直接跑:

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

您可以编写一个循环或理解,使其对元组列表中的所有元素执行此操作,或者对字典中的键和值执行此操作,具体取决于如何存储实际数据。

如果 dfpandas.DataFrame,那么 df['new_col']= Series list_object of length len(df)将添加或 Series list _ object 作为名为 'new_col'的列。df['new_col']= scalar(例如5或6)也可以工作,相当于 df['new_col']= [scalar]*len(df)

因此,两行代码的作用是:

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

如今,更为简洁的解决方案可以实现同样的任务。利用 DataFrame.apply()将 Series 转换为其所属 DataFrame 的列的能力,我们可以使用:

df.join(df.apply(lambda x: s, axis=1))

结果:

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

在这里,我们使用 DataFrame.apply()和一个简单的 lambda 函数作为应用于 axis=1的函数。应用的 lambda 函数只返回 Series s:

df.apply(lambda x: s, axis=1)

结果:

   s1  s2
3   5   6
5   5   6
6   5   6

The result has already inherited the row index of the original DataFrame df. Consequently, we can simply join df with this interim result by DataFrame.join() to get the desired final result (since they have the same row index).

DataFrame.apply()将 Series 转换为其所属 DataFrame 的列的能力在 official document中有详细的文档记录如下:

默认情况下(result _ type = Nothing) ,最终返回类型是从 应用函数的返回类型。


默认行为(result _ type = Nothing)取决于 应用函数: 类似列表的结果将作为系列返回 但是,如果 application 函数返回一个 Series,则 < em > < strong > 扩展到列 。

正式文件还包括这种用法的例子:

Returning a Series inside the function is similar to passing 结果列名称将为 Series 索引。

df.apply(lambda x: pd.Series([1, 2], index=['foo', 'bar']), axis=1)


foo  bar
0    1    2
1    1    2
2    1    2