如果您来到这里寻找如何获取的信息 在索引上合并
DataFrame
和Series
,请查看this answer。OP的初衷是要求如何分配系列元素 作为另一个DataFrame的列。如果你有兴趣知道 回答这个问题,看看EdChum的accepted answer。
我能想出的最好的是
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
答案 0 :(得分:114)
<强>更新强>
从v0.24.0开始,只要系列被命名,就可以在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()的DataFrame即可。所以(如果加入索引):
df.merge(s.to_frame(), left_index=True, right_index=True)
答案 1 :(得分:15)
您可以从系列中构造一个数据框,然后与数据框合并。 因此,您将数据指定为值,但将它们乘以长度,将列设置为索引并将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 :(得分:3)
这是一种方式:
df.join(pd.DataFrame(s).T).fillna(method='ffill')
要打破这里发生的事情......
pd.DataFrame(s).T
从s
创建一行DataFrame,如下所示:
s1 s2
0 5 6
接下来,join
将此新框架与df
:
a b s1 s2
0 1 3 5 6
1 2 4 NaN NaN
最后,索引1处的NaN
值使用带有前向填充(fillna
)参数的ffill
填充列中的先前值:
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
。
答案 3 :(得分:0)
如果我可以建议您设置这样的数据帧(自动索引):
df = pd.DataFrame({'a':[np.nan, 1, 2], 'b':[4, 5, 6]})
然后你可以设置你的s1和s2值(使用shape()来返回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
如果您有另一个数据列表(而不是仅应用一个值),并且您知道它与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
答案 4 :(得分:0)
您可以轻松地将pandas.DataFrame列设置为常量。这个常数可以是int,例如您的示例。如果您指定的列不在df中,则pandas将使用您指定的名称创建一个新列。因此,在构造完数据框之后,(根据您的问题):
df = pd.DataFrame({'a':[np.nan, 2, 3], 'b':[4, 5, 6]}, index=[3, 5, 6])
您可以运行:
df['s1'], df['s2'] = 5, 6
您可以编写循环或理解来使它对元组列表中的所有元素,字典中的键和值进行此操作,具体取决于您存储真实数据的方式。
答案 5 :(得分:0)
如果df
是pandas.DataFrame
,则df['new_col']= Series list_object of length len(df)
将or或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
答案 6 :(得分:0)
如今,更简单和简洁的解决方案可以实现相同的任务。利用 DataFrame.apply()
的功能将系列转换为其所属 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
结果已经继承了原 DataFrame df
的行索引。因此,我们可以简单地通过 DataFrame.join()
将 df
与这个临时结果连接起来,以获得所需的最终结果(因为它们具有相同的行索引)。
DataFrame.apply()
将系列转换为其所属 DataFrame 的列的这种功能在 official document 中有详细记录,如下所示:
默认情况下(result_type=None),最终的返回类型是从 应用函数的返回类型。
默认行为(result_type=None)取决于返回值 应用函数:类似列表的结果将作为一系列返回 那些。但是如果应用函数返回一个系列,这些是 扩展到列。
official document 还包括此类用法的示例:
<块引用>在函数内部返回一个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