pandas 如何合并Series和DataFrame

nhjlsmyf  于 2023-05-12  发布在  其他
关注(0)|答案(7)|浏览(244)

如果你来这里寻找有关 * 如何在索引上合并DataFrameSeries * 的信息,请查看this answer
OP的初衷是询问 * 如何将series元素作为列分配给另一个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
nzk0hqpo

nzk0hqpo1#

更新

从v0.24.0开始,只要命名了Series,就可以在DataFrame和Series上执行merge

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

eanckbw92#

您可以从该系列构造一个 Dataframe ,然后与该 Dataframe 合并。因此,您将数据指定为值,但将其乘以长度,将列设置为索引,并将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

EDIT对于您希望从系列中构造的df的索引使用df的索引的情况,那么您可以执行以下操作:

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

这假设索引与长度匹配。

hfsqlsce

hfsqlsce3#

这里有一个方法:

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和forward-fill(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))

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

dddzy1tm

dddzy1tm4#

如今,更简单和简洁的解决方案可以实现相同的任务。利用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

结果已经继承了原始DataFrame df的行索引。因此,我们可以简单地通过DataFrame.join()df与这个中间结果连接起来,以获得所需的最终结果(因为它们具有相同的行索引)。
DataFrame.apply()将Series转换为所属DataFrame的列的功能在official document中有详细说明,如下所示:
默认情况下(result_type=None),最终返回类型是从应用函数的返回类型推断出来的。
默认行为(result_type=None)取决于所应用函数的返回值:类似列表的结果将作为这些结果的系列返回。但是***如果apply函数返回一个Series,则这些列将展开为列***。
official document还包括这种用法的示例:
在函数内部返回Series类似于传递result_type='expand'。生成的列名将是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
mo49yndu

mo49yndu5#

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

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

或者,只需将新值添加到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
5t7ly7z5

5t7ly7z56#

您可以轻松地将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

你可以编写一个循环或解析,让它对元组列表中的所有元素或字典中的键和值执行此操作,这取决于你如何存储真实的数据。

ewm0tg9j

ewm0tg9j7#

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

相关问题