如何合并Series和DataFrame

时间:2014-10-08 20:27:27

标签: python pandas dataframe

  

如果您来到这里寻找如何获取的信息   在索引上合并DataFrameSeries,请查看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

7 个答案:

答案 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).Ts创建一行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)

如果dfpandas.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