Pandy wybierając po etykiecie czasami zwracają serie, czasami zwracają DataFrame

W pandach, kiedy zaznaczam etykietę, która ma tylko jeden wpis w indeksie, otrzymuję serię, ale kiedy zaznaczam wpis, który ma więcej niż jeden wpis, otrzymuję ramkę danych.

Dlaczego? Czy istnieje sposób, aby zapewnić, że zawsze odzyskam ramkę danych?
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
Author: smci, 2013-12-04

7 answers

Przyznam, że zachowanie jest niespójne, ale myślę, że łatwo wyobrazić sobie przypadki, w których jest to wygodne. W każdym razie, aby uzyskać ramkę danych za każdym razem, po prostu przekaż listę loc. Są inne sposoby, ale moim zdaniem to jest najczystsze.

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

In [3]: type(df.loc[[1]])
Out[3]: pandas.core.frame.DataFrame
 111
Author: Dan Allan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-04 19:36:17

Masz Indeks z trzema elementami indeksu 3. Z tego powodu df.loc[3] zwróci ramkę danych.

Powodem jest to, że nie podajesz kolumny. Tak więc df.loc[3] wybiera trzy pozycje wszystkich kolumn( co jest kolumną 0), podczas gdy df.loc[3,0] zwróci serię. Np. df.loc[1:2] zwraca również ramkę danych, ponieważ przecinasz wiersze.

Wybranie pojedynczego wiersza (jako df.loc[1]) zwraca serię z nazwami kolumn jako indeks.

Jeśli chcesz mieć pewność, że zawsze masz ramkę danych, możesz kroić jak df.loc[1:1]. Inną opcją jest indeksowanie logiczne (df.loc[df.index==1]) lub metoda take (df.take([0]), ale ta używana lokalizacja Nie etykiety!).

 17
Author: joris,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-04 19:33:29

Użyj df['columnName'], aby uzyskać szereg i df[['columnName']], Aby uzyskać ramkę danych.

 7
Author: user4422,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-04 07:57:51

TLDR

Podczas używania loc

df.loc[:] = Dataframe

df.loc[int] = Dataframe Jeśli masz więcej niż jedną kolumnę i seria Jeśli masz tylko 1 kolumnę w dataframe

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

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

Nie używam loc

df["col_name"] = seria

df[["col_name"]] = Dataframe

 7
Author: Colin Anthony,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-11-15 10:09:34

Napisałeś w komentarzu do odpowiedzi Jorisa:

" nie rozumiem projektu decyzja dla pojedynczych wierszy do get converted into a series-why not a ramka danych z jednym wierszem?"

Pojedynczy wiersz nie jest konwertowany w szereg.
It IS a Series: No, I don't think so, in fact; see the edit

Najlepszy sposób myślenia o strukturach danych pandy jest tak elastyczny kontenery dla danych o niższych wymiarach. Na przykład, DataFrame jest pojemnik na Seria, A Panel jest kontenerem dla obiektów DataFrame. Chcielibyśmy móc wstawiać i usuwać obiekty z tych kontenery w sposób słownikowy.

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

Model danych obiektów Pandy został wybrany w ten sposób. Powodem z pewnością jest to, że zapewnia pewne korzyści, których nie znam (nie do końca rozumiem ostatnie zdanie cytowanie, może to jest powód)

.

Edit: nie zgadzam się ze sobą

Ramka Danych nie może składać się z elementów, które będą seriami, ponieważ poniższy kod daje ten sam typ "Series", jak również dla wiersza jak dla kolumny:

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

Wynik

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

Więc nie ma sensu udawać, że ramka danych składa się z serii, ponieważ co te wspomniane serie mają być: kolumny lub wiersze ? Głupie pytanie i wizja.

.

Więc co to jest ramka danych ?

W poprzedniej wersji tej odpowiedzi zadałem to pytanie, starając się znaleźć odpowiedź na Why is that? część pytania OP i podobne przesłuchanie single rows to get converted into a series - why not a data frame with one row? w jednym z jego komentarzy,
podczas gdy na Część Is there a way to ensure I always get back a data frame? odpowiedział Dan Allan.

Następnie, jak wyżej cytowane dokumenty Pandy mówią, że struktury danych pandy są najlepiej postrzegane jako kontenery danych o niższych wymiarach, wydawało mi się, że zrozumienie dlaczego {[56] } znajdowałoby się w charakterystyce natury struktur ramek danych.

Zdałem sobie jednak sprawę, że ta przytoczona Rada nie może być traktowana jako dokładny opis natury struktur danych Pandy.
Ta rada nie oznacza, że ramka danych jest kontenerem serii.
Wyraża, że mentalna reprezentacja ramki danych jako kontenera szeregów (wierszy lub kolumn zgodnie z opcją rozważaną w jednym momencie rozumowanie) jest dobrym sposobem na rozważenie ramek danych, nawet jeśli nie jest to ściśle prawda w rzeczywistości. "Dobre" oznacza, że ta wizja pozwala na efektywne wykorzystanie RAM danych. To wszystko.

.

Więc czym jest obiekt DataFrame ?

Klasa DataFrame tworzy instancje, które mają określoną strukturę wywodzącą się z klasy bazowej Ndframe, wywodzącej się z klasy bazowej PandasContainer, która jest również klasą nadrzędną Seria Klasa.
Zauważ, że jest to poprawne dla pand do wersji 0.12. W nadchodzącej wersji 0.13, seria będzie również wywodzić się tylko z klasy 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__

Wynik

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

Więc teraz rozumiem, że instancja DataFrame ma pewne metody, które zostały opracowane w celu kontrolowania sposobu, w jaki dane są wydobywane z wierszy i kolumn.

Sposoby działania tych metod ekstrakcyjnych opisane są w tym strona: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing
Znajdujemy w nim metodę podaną przez Dana Allana i inne metody.

Dlaczego te metody ekstrakcji zostały opracowane tak, jak były ?
To z pewnością dlatego, że zostały one ocenione jako te dające lepsze możliwości i łatwość w analizie danych.
Jest to dokładnie to, co jest wyrażone w tym zdaniu:

Najlepszym sposobem myślenia o strukturach danych pandy jest elastyczne kontenery dla danych o niższych wymiarach.

dlaczego ekstrakcji danych z instancji ramki danych nie leży w jej strukturze, lecz w dlaczego tej struktury. Myślę, że struktura i funkcjonalność struktury danych Pandy zostały wyrzeźbione tak, aby były jak najbardziej intuicyjne intelektualnie, a aby zrozumieć szczegóły, trzeba przeczytać blog Wesa Mckinneya.

 3
Author: eyquem,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-05 01:46:28

Jeśli celem jest uzyskanie podzbioru zbioru danych za pomocą indeksu, najlepiej unikać używania loc lub iloc. Zamiast tego powinieneś użyć składni podobnej do tej:

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
 1
Author: Ajit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-26 07:37:57

Jeśli wybierzesz również indeks ramki danych, to wynikiem może być ramka danych lub Seria lub może być seria lub Skalar (pojedyncza wartość).

Ta funkcja zapewnia, że zawsze otrzymasz listę z zaznaczenia (jeśli DF, indeks i Kolumna są ważne):

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)
 0
Author: Wouter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-03-23 08:50:30