[python] 라벨로 선택하는 Pandas는 때때로 Series를 반환하고 때로는 DataFrame을 반환합니다.

Pandas에서 인덱스에 항목이 하나만있는 레이블을 선택하면 Series가 반환되지만 항목이 하나 이상있는 항목을 선택하면 데이터 프레임이 반환됩니다.

왜 그런 겁니까? 항상 데이터 프레임을 되 찾을 수있는 방법이 있습니까?

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



답변

행동이 일관 적이 지 않다는 것은 인정하지만 이것이 편리한 경우를 상상하기 쉽다고 생각합니다. 어쨌든 매번 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


답변

세 개의 인덱스 항목이있는 인덱스가 있습니다 3. 이러한 이유로 df.loc[3]데이터 프레임을 반환합니다.

그 이유는 열을 지정하지 않았기 때문입니다. 따라서 df.loc[3]모든 열 (column 0) 의 세 항목을 선택 df.loc[3,0]하고 Series를 반환합니다. 예를 들어 df.loc[1:2]행을 분할하기 때문에 데이터 프레임도 반환됩니다.

단일 행 ( df.loc[1])을 선택하면 열 이름을 인덱스로 사용하는 Series가 반환됩니다.

항상 DataFrame을 갖고 싶다면 df.loc[1:1]. 또 다른 옵션은 부울 인덱싱 ( df.loc[df.index==1]) 또는 take 메소드 ( df.take([0]),하지만 레이블이 아닌 위치를 사용했습니다!)입니다.


답변

df['columnName']Series df[['columnName']]를 가져 오고 Dataframe을 가져 오는 데 사용 합니다 .


답변

TLDR

사용할 때 loc

df.loc[:]= Dataframe

df.loc[int]= Dataframe 개 이상의 열과 경우 시리즈 는 dataframe 만 1 열이있는 경우

df.loc[:, ["col_name"]]= Dataframe

df.loc[:, "col_name"] = 시리즈

사용하지 않음 loc

df["col_name"]= 시리즈

df[["col_name"]]= Dataframe


답변

당신은 joris의 대답에 대한 의견을 썼습니다.

“단일 행을 시리즈로 변환 하기위한 설계 결정을 이해하지 못합니다. 행 이 하나 인 데이터 프레임은 어떻습니까?”

단일 행은 시리즈에서 변환 되지 않습니다 .
그것은 IS 시리즈 :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-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로 구성된 척하는 것은 의미가 없습니다. 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의 컨테이너라는 것을 의미하지 않습니다.
Series의 컨테이너 (추론의 한 순간에 고려되는 옵션에 따라 행 또는 열)로서의 DataFrame의 정신적 표현이 실제로는 엄격하지 않더라도 DataFrames를 고려하는 좋은 방법임을 표현합니다. “Good”은이 비전이 DataFrame을 효율적으로 사용할 수 있음을 의미합니다. 그게 다야.

.

그렇다면 DataFrame 객체는 무엇입니까?

DataFrame의 클래스는 특정 구조는 유래가 인스턴스 생성 NDFrame의 베이스 클래스, 자체로부터 도출 PandasContainer의 도의 상위 클래스 인 기본 클래스 시리즈 클래스.
이것은 버전 0.12까지 Pandas에 대해 정확합니다. 다가오는 버전 0.13에서 SeriesNDFrame 클래스에서만 파생 됩니다.

# 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 및 기타 방법이 제공 한 방법을 찾을 수 있습니다.

이러한 추출 방법이 원래대로 만들어진 이유는 무엇입니까?
데이터 분석에서 더 나은 가능성과 용이성을 제공하는 것으로 평가 되었기 때문입니다.
이 문장에서 정확히 표현되는 것은 다음과 같습니다.

Pandas 데이터 구조에 대해 생각하는 가장 좋은 방법은 저 차원 데이터를위한 유연한 컨테이너입니다.

DataFRame 인스턴스에서 데이터를 추출 하는 이유 는 구조에있는 것이 아니라이 구조의 이유 에 있습니다. Pandas의 데이터 구조의 구조와 기능은 최대한 지적으로 직관적이되도록 깎아 내렸고 세부 사항을 이해하려면 Wes McKinney의 블로그를 읽어야합니다.


답변

색인을 사용하여 데이터 세트의 하위 집합을 가져 오는 것이 목표 인 경우 loc또는을 사용하지 않는 것이 가장 좋습니다 iloc. 대신 다음과 유사한 구문을 사용해야합니다.

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


답변

데이터 프레임의 인덱스에서도 선택하면 결과는 DataFrame 또는 Series 이거나 Series 또는 스칼라 (단일 값) 일 수 있습니다.

이 함수를 사용하면 선택 항목에서 항상 목록을 가져올 수 있습니다 (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)