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
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
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!).
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.
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
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.
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
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)
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