将Pandas数据框转换为系列。

153
我对pandas还有点陌生。我有一个1行23列的pandas数据框。
我想把它转换成一个系列。我想知道最符合Python风格的方法是什么?
我尝试过`pd.Series(myResults)`,但它报错说`ValueError: cannot copy sequence with size 23 to array axis with dimension 1`。它没有聪明到足够意识到在数学术语中它仍然是一个"向量"。
8个回答

108
您可以转置单行数据框(仍然会得到一个数据框),然后将结果压缩成系列数据(与to_frame的相反操作)。
df = pd.DataFrame([list(range(5))], columns=["a{}".format(i) for i in range(5)])

>>> df.squeeze(axis=0)
a0    0
a1    1
a2    2
a3    3
a4    4
Name: 0, dtype: int64

注意: 要考虑到@IanS提出的一点(尽管这不在OP的问题中),检查数据框的大小。我假设df是一个数据框,但边缘情况包括空数据框,一个形状为(1,1)的数据框以及一个有多行的数据框,在这种情况下,用户应该实现他们想要的功能。

if df.empty:
    # Empty dataframe, so convert to empty Series.
    result = pd.Series()
elif df.shape == (1, 1)
    # DataFrame with one value, so convert to series with appropriate index.
    result = pd.Series(df.iat[0, 0], index=df.columns)
elif len(df) == 1:
    # Convert to series per OP's question.
    result = df.T.squeeze()
else:
    # Dataframe with multiple rows.  Implement desired behavior.
    pass

这也可以按照@themachinist提供的答案进行简化。

if len(df) > 1:
    # Dataframe with multiple rows.  Implement desired behavior.
    pass
else:
    result = pd.Series() if df.empty else df.iloc[0, :]

15
请注意,我在使用squeeze时遇到了一些小问题。对于形状为(1, 1)的数据帧,它将返回一个NumPy标量,而不是长度为1的系列。这会导致在对长度未知的对象(例如使用groupby)使用squeeze时出现难以捕捉的错误。 - IanS
2
谢谢!在 df.iloc[:,0] 和 df.ix[:,0] 都产生太多索引错误的情况下,df.squeeze() 起作用了。 - Afflatus
4
为什么to_frame的逆操作不是to_seriespd.Series(df)呢? - Eike P.
5
不需要.T - elgehelge
4
请将参数df.squeeze(axis=0)df.squeeze(axis=1)(取决于您想保留的轴)传递给IanS,以避免这种情况发生。请注意不改变原始意思,使句子更通俗易懂。 - Nicolas Fonteyne
我认为始终指定要压缩的轴是明智的。 - Levi Baguley

82

从数学角度来说,它并不足够聪明地意识到它仍然是一个“向量”。

可以说它足够聪明,能够识别维度的差异。 :-)

我认为最简单的方法是使用iloc按位置选择该行,这将给你一个系列对象,其中列是新的索引,值是相应的值:

>>> df = pd.DataFrame([list(range(5))], columns=["a{}".format(i) for i in range(5)])
>>> df
   a0  a1  a2  a3  a4
0   0   1   2   3   4
>>> df.iloc[0]
a0    0
a1    1
a2    2
a3    3
a4    4
Name: 0, dtype: int64
>>> type(_)
<class 'pandas.core.series.Series'>

2
或者,另一种方式是:df.T - ako
16
df.T不会产生一个Series,仅会得到一个转置后的DataFrame。 - DSM
1
@DSM。没错,df.T.iloc[0] - Antonio Andrés
1
使用 df.iloc 的唯一问题是,如果您有一个空的 df,则会引发 IndexError。为了避免这种情况,在转置 df 后,请使用 df.squeeze 方法。参考 https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.squeeze.html - Nicolas Fonteyne
@DSM 是的,使用 df.iloc 是最好的方法! - Sherman Chen

39

15
如果您有一个一列的DataFrame df,您可以将其转换为一个Series:
df.iloc[:,0]  # pandas Series

由于你有一个一行数据框 df,你可以转置它以使其符合之前的情况:

df.T.iloc[:,0]

10

你也可以使用 stack()

df= DataFrame([list(range(5))], columns = [“a{}”.format(I) for I in range(5)])

运行df命令后,再输入以下命令:

df.stack()

您可以通过序列获得数据框。


stack()是唯一足够强大的解决方案,可以确保不返回单个元素而不是预期的单列... - mirekphd

6

另一种方式 -

假设myResult是包含您的数据的数据框,以1列和23行的形式呈现。

# label your columns by passing a list of names
myResult.columns = ['firstCol']

# fetch the column in this way, which will return you a series
myResult = myResult['firstCol']

print(type(myResult))

以类似的方式,你可以从具有多列的数据框中获取系列。

1
另一种方法非常简单。
df= df.iloc[3].reset_index(drop=True).squeeze()

挤压(Squeeze)是将其转换为系列(Series)的函数。

1
data = pd.DataFrame({"a":[1,2,3,34],"b":[5,6,7,8]})
new_data = pd.melt(data)
new_data.set_index("variable", inplace=True)

这会生成一个数据框,其中索引作为数据的列名,所有数据都存在“values”列中。

6
欢迎来到 Stack Overflow!这个回答如何解决问题?你的代码没有返回一个像问题所要求的 Series。 - Gricey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接