Pandas 按标签选择有时会返回 Series,有时会返回 DataFrame

2025-04-16 08:57:00
admin
原创
19
摘要:问题描述:在 Pandas 中,当我选择索引中只有一个条目的标签时,我会返回一个系列,但是当我选择一个具有多个条目的条目时,我会返回一个数据框。这是为什么?有什么方法可以确保我每次都能返回数据帧吗?In [1]: import pandas as pd In [2]: df = pd.DataFrame(d...

问题描述:

在 Pandas 中,当我选择索引中只有一个条目的标签时,我会返回一个系列,但是当我选择一个具有多个条目的条目时,我会返回一个数据框。

这是为什么?有什么方法可以确保我每次都能返回数据帧吗?

In [1]: import pandas as pd

In [2]: df = pd.DataFrame(data=range(5), index=[1, 2, 3, 3, 3])

In [3]: type(df.loc[3])
Out[3]: pandas.core.frame.DataFrame

In [4]: type(df.loc[1])
Out[4]: pandas.core.series.Series

解决方案 1:

诚然,这种行为可能不一致,但我认为很容易想象到这种做法很方便的情况。总之,每次要获取 DataFrame 时,只需将列表传递给 即可loc。当然还有其他方法,但我认为这是最简洁的。

In [2]: type(df.loc[[3]])
Out[2]: pandas.core.frame.DataFrame

In [3]: type(df.loc[[1]])
Out[3]: pandas.core.frame.DataFrame

解决方案 2:

TLDR

使用时loc

df.loc[:]=数据框

df.loc[int]=数据框(如果数据框中有多个列)和系列(如果数据框中只有 1 列)

df.loc[:, ["col_name"]]= Dataframe(如果选择中有多个行)和Series(如果选择中只有 1 行)

df.loc[:, "col_name"]=系列

不使用loc

df["col_name"]=系列

df[["col_name"]]=数据框

解决方案 3:

您的索引包含三个索引项3。因此df.loc[3]将返回一个数据框。

原因是你没有指定列。因此,df.loc[3]它会选择所有列(即 column 0)中的三个项目,同时df.loc[3,0]返回一个 Series。例如,df.loc[1:2]由于你对行进行了切片,因此也会返回一个 DataFrame。

选择单行(如df.loc[1])将返回以列名作为索引的系列。

如果要确保始终拥有 DataFrame,可以像 一样进行切片df.loc[1:1]。另一个选项是布尔索引 ( df.loc[df.index==1]) 或 take 方法 ( df.take([0]),但这使用的是位置而不是标签!)。

解决方案 4:

用于df['columnName']获取系列并df[['columnName']]获取数据框。

解决方案 5:

您在对 joris 的回答的评论中写道:

“我不明白将单行转换为一系列的设计决策 - 为什么不使用一行的数据框?”

单行不会被转换为系列。

一个系列:No, I don't think so, in fact; see the edit

理解 Pandas 数据结构的最佳方式是将其视为低维数据的灵活容器。例如,DataFrame 是 Series 的容器,而 Panel 是 DataFrame 对象的容器。我们希望能够以类似字典的方式在这些容器中插入和删除对象。

http://pandas.pydata.org/pandas-docs/stable/overview.html#why-more-than-1-data-struct

Pandas 对象的数据模型就是这样选择的。原因当然在于它能带来一些我不知道的优势(我不太理解引文最后一句的意思,也许这就是原因)。

编辑:我不同意我的观点

DataFrame 不能由 Series 元素组成因为以下代码为行和列提供了相同的类型“Series”:

import pandas as pd

df = pd.DataFrame(data=[11,12,13], index=[2, 3, 3])

print '-------- df -------------'
print df

print '
------- df.loc[2] --------'
print df.loc[2]
print 'type(df.loc[1]) : ',type(df.loc[2])

print '
--------- df[0] ----------'
print df[0]
print 'type(df[0]) : ',type(df[0])

结果

-------- df -------------
    0
2  11
3  12
3  13

------- df.loc[2] --------
0    11
Name: 2, dtype: int64
type(df.loc[1]) :  <class 'pandas.core.series.Series'>

--------- df[0] ----------
2    11
3    12
3    13
Name: 0, dtype: int64
type(df[0]) :  <class 'pandas.core.series.Series'>

所以,假装 DataFrame 由 Series 组成是没有意义的,因为这些 Series 应该是什么:列还是行?真是愚蠢的问题和想法。

那么什么是 DataFrame ?

在这个答案的先前版本中,我提出了这个问题,试图找到Why is that?OP 问题的一部分以及single rows to get converted into a series - why not a data frame with one row?他的一条评论中的类似询问的答案,

而该Is there a way to ensure I always get back a data frame?部分已经由 Dan Allan 回答。

然后,正如上面引用的 Pandas 文档所说,pandas 的数据结构最好被视为低维数据的容器,在我看来,对原因的理解可以在 DataFrame 结构性质的特征中找到。

然而,我意识到,这条建议并不能被理解为对 Pandas 数据结构本质的准确描述。

这条建议并不意味着 DataFrame 是 Series 的容器。

它表明,将 DataFrame 视为 Series 的容器(根据推理过程中的某个时刻的选项,可以是行,也可以是列)是一种理解 DataFrame 的好方法,即使现实情况并非如此。“好”是指这种设想能够高效地使用 DataFrame。仅此而已。

那么什么是 DataFrame 对象?

DataFrame类生成的实例具有源自NDFrame基类的特定结构,而 NDFrame 基类本身派生自 PandasContainer 基类,而 PandasContainer基类也是Series类的父类。

请注意,在 Pandas 0.12 版本之前,此方法是正确的。在即将推出的 0.13 版本中,Series也将仅派生自NDFrame类。

# with pandas 0.12

from pandas import Series
print 'Series  :
',Series
print 'Series.__bases__  :
',Series.__bases__

from pandas import DataFrame
print '
DataFrame  :
',DataFrame
print 'DataFrame.__bases__  :
',DataFrame.__bases__

print '
-------------------'

from pandas.core.generic import NDFrame
print '
NDFrame.__bases__  :
',NDFrame.__bases__

from pandas.core.generic import PandasContainer
print '
PandasContainer.__bases__  :
',PandasContainer.__bases__

from pandas.core.base import PandasObject
print '
PandasObject.__bases__  :
',PandasObject.__bases__

from pandas.core.base import StringMixin
print '
StringMixin.__bases__  :
',StringMixin.__bases__

结果

Series  :
<class 'pandas.core.series.Series'>
Series.__bases__  :
(<class 'pandas.core.generic.PandasContainer'>, <type 'numpy.ndarray'>)

DataFrame  :
<class 'pandas.core.frame.DataFrame'>
DataFrame.__bases__  :
(<class 'pandas.core.generic.NDFrame'>,)

-------------------

NDFrame.__bases__  :
(<class 'pandas.core.generic.PandasContainer'>,)

PandasContainer.__bases__  :
(<class 'pandas.core.base.PandasObject'>,)

PandasObject.__bases__  :
(<class 'pandas.core.base.StringMixin'>,)

StringMixin.__bases__  :
(<type 'object'>,)

所以我现在的理解是,DataFrame 实例具有某些方法,这些方法是为了控制从行和列中提取数据的方式而设计的。

这些提取方法的工作方式在本页面中有描述:
http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing

我们在其中找到了 Dan Allan 给出的方法和其他方法。

为什么要设计这些提取方法?

当然是因为它们被认为能够提供更好的可能性,并且简化数据分析。

这句话表达的正是这一点:

思考熊猫数据结构的最佳方式是将其作为低维数据的灵活容器。

从 DataFRame 实例中提取数据的原因不在于其结构,而在于这种结构本身意义。我猜想,Pandas 数据结构的结构和功能已经经过精心设计,以便尽可能直观易懂。要理解其中的细节,可以阅读 Wes McKinney 的博客。

解决方案 6:

如果目标是使用索引获取数据集的子集,最好避免使用lociloc。而应该使用类似这样的语法:

df = pd.DataFrame(data=range(5), index=[1, 2, 3, 3, 3])
result = df[df.index == 3] 
isinstance(result, pd.DataFrame) # True

result = df[df.index == 1]
isinstance(result, pd.DataFrame) # True

解决方案 7:

每次我们放入[['column name']]它都会返回 Pandas DataFrame 对象,如果我们放入['column name']我们得到 Pandas Series 对象

解决方案 8:

如果您还选择数据框的索引,那么结果可以是数据框或系列,也可以是系列或标量(单个值)。

此函数可确保您始终从您的选择中获取一个列表(如果 df、索引和列有效):

def get_list_from_df_column(df, index, column):
    df_or_series = df.loc[index,[column]] 
    # df.loc[index,column] is also possible and returns a series or a scalar
    if isinstance(df_or_series, pd.Series):
        resulting_list = df_or_series.tolist() #get list from series
    else:
        resulting_list = df_or_series[column].tolist() 
        # use the column key to get a series from the dataframe
    return(resulting_list)
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2482  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1533  
  PLM(产品生命周期管理)项目对于企业优化产品研发流程、提升产品质量以及增强市场竞争力具有至关重要的意义。然而,在项目推进过程中,范围蔓延是一个常见且棘手的问题,它可能导致项目进度延迟、成本超支以及质量下降等一系列不良后果。因此,有效避免PLM项目范围蔓延成为项目成功的关键因素之一。以下将详细阐述三大管控策略,助力企业...
plm系统   0  
  PLM(产品生命周期管理)项目管理在企业产品研发与管理过程中扮演着至关重要的角色。随着市场竞争的加剧和产品复杂度的提升,PLM项目面临着诸多风险。准确量化风险优先级并采取有效措施应对,是确保项目成功的关键。五维评估矩阵作为一种有效的风险评估工具,能帮助项目管理者全面、系统地评估风险,为决策提供有力支持。五维评估矩阵概述...
免费plm软件   0  
  引言PLM(产品生命周期管理)开发流程对于企业产品的全生命周期管控至关重要。它涵盖了从产品概念设计到退役的各个阶段,直接影响着产品质量、开发周期以及企业的市场竞争力。在当今快速发展的科技环境下,客户对产品质量的要求日益提高,市场竞争也愈发激烈,这就使得优化PLM开发流程成为企业的必然选择。缺陷管理工具和六西格玛方法作为...
plm产品全生命周期管理   0  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用