按标签选择的熊猫有时会返回系列,有时会返回数据帧

时间:2013-12-04 19:01:40

标签: python pandas dataframe slice

在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

7 个答案:

答案 0 :(得分:77)

假设行为不一致,但我认为很容易想象这很方便的情况。无论如何,要每次都获得一个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

答案 1 :(得分:12)

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

原因是您没有指定列。因此df.loc[3]会选择所有列中的三个项目(列0),而df.loc[3,0]将返回一个系列。例如。 df.loc[1:2]也会返回一个数据帧,因为您对行进行切片。

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

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

答案 2 :(得分:3)

您在对joris的回答中写道:

  

“我不懂设计   决定将转换的单行转换为系列 - 为什么不是a   有一行的数据框?“

系列中的单行不是已转换 IS 系列:No, I don't think so, in fact; see the edit

  

考虑大熊猫数据结构的最佳方式是灵活的   用于低维数据的容器。例如,DataFrame是一个   Series的容器,Panel是DataFrame对象的容器。   我们希望能够插入和删除这些对象   容器以类似字典的方式。

     

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

Pandas对象的数据模型就是这样选择的。原因当然在于它确保了一些我不知道的优点(我不完全理解引用的最后一句话,也许这就是原因)

编辑:我不同意我

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

import pandas as pd

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

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

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

print '\n--------- 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组成是没有意义的,因为这些系列应该是什么:列或行?愚蠢的问题和愿景。

那么什么是DataFrame?

在这个答案的上一个版本中,我提出了这个问题,试图在他的一条评论中找到OP问题的Why is that?部分的答案和类似的审讯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?部分。

然后,正如上面引用的熊猫文档所说,大熊猫的数据结构最好被视为低维数据的容器,在我看来,理解为什么< / em>可以在DataFrame结构的本质特征中找到。

但是,我意识到这个引用的建议不能被视为对熊猫数据结构性质的精确描述。
这个建议并不意味着DataFrame是Series的容器 它表示DataFrame作为Series的容器(根据推理的某个时刻考虑的选项的行或列)的心理表示是考虑DataFrames的好方法,即使它实际上并非严格的情况。 “好”意味着此愿景可以高效地使用DataFrame。就是这样。

那么什么是DataFrame对象?

DataFrame 类生成的实例具有源自 NDFrame 基类的特定结构,该基类本身派生自 PandasContainer 基类,即也是系列类的父类 请注意,这对于Pandas来说是正确的,直到版本0.12。在即将推出的0.13版中,系列也仅来自 NDFrame 类。

# with pandas 0.12

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

from pandas import DataFrame
print '\nDataFrame  :\n',DataFrame
print 'DataFrame.__bases__  :\n',DataFrame.__bases__

print '\n-------------------'

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

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

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

from pandas.core.base import StringMixin
print '\nStringMixin.__bases__  :\n',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实例中提取数据的原因不在于它的结构,它位于此结构的 why 中。我想Pandas的数据结构的结构和功能已被凿刻,以尽可能在智力上直观,并且为了理解细节,必须阅读Wes McKinney的博客。

答案 3 :(得分:3)

使用df['columnName']获取序列,使用df[['columnName']]获取数据框。

答案 4 :(得分:1)

如果目标是使用索引获取数据集的子集,则最好避免使用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

答案 5 :(得分:1)

TLDR

使用auth:admin

Route::view('admin', 'admin')->middleware('auth:admin'); = 数据框

loc = 数据框(如果您有多个列),并且系列(如果数据框中只有1列)

df.loc[:] = 数据框

df.loc[int] = 系列

不使用df.loc[:, ["col_name"]]

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

loc = 数据框

答案 6 :(得分:0)

If you also select on the index of the dataframe then the result can be either a DataFrame or a Series or it can be a Series or a scalar (single value).

This function ensures that you always get a list from your selection (if the df, index and column are valid):

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)