Pandy Pythona: Zachowaj wybraną kolumnę jako DataFrame zamiast Series

92

Po wybraniu pojedynczej kolumny z pandy DataFrame (powiedzmy df.iloc[:, 0], df['A']lub df.A, itp.), Wynikowy wektor jest automatycznie konwertowany na Series zamiast na pojedynczą kolumnę DataFrame. Jednak piszę niektóre funkcje, które przyjmują DataFrame jako argument wejściowy. Dlatego wolę zajmować się pojedynczą kolumną DataFrame zamiast Series, aby funkcja mogła założyć, że df.columns jest dostępne. W tej chwili muszę jawnie przekonwertować Series na DataFrame, używając czegoś takiego jak pd.DataFrame(df.iloc[:, 0]). To nie wydaje się najczystszą metodą. Czy istnieje bardziej elegancki sposób indeksowania bezpośrednio z DataFrame, tak aby wynik był jednokolumnowym DataFrame zamiast Series?


źródło
6
df.iloc [:, [0]] lub df [['A']]; df.A tylko odda jednak serię
Jeff

Odpowiedzi:

99

Jak wspomina @Jeff, jest kilka sposobów, aby to zrobić, ale polecam użycie loc / iloc, aby być bardziej wyraźnym (i zgłaszać błędy wcześniej, jeśli próbujesz czegoś niejednoznacznego):

In [10]: df = pd.DataFrame([[1, 2], [3, 4]], columns=['A', 'B'])

In [11]: df
Out[11]:
   A  B
0  1  2
1  3  4

In [12]: df[['A']]

In [13]: df[[0]]

In [14]: df.loc[:, ['A']]

In [15]: df.iloc[:, [0]]

Out[12-15]:  # they all return the same thing:
   A
0  1
1  3

Dwie ostatnie opcje eliminują niejednoznaczność w przypadku nazw kolumn zawierających liczby całkowite (właśnie dlatego utworzono loc / iloc). Na przykład:

In [16]: df = pd.DataFrame([[1, 2], [3, 4]], columns=['A', 0])

In [17]: df
Out[17]:
   A  0
0  1  2
1  3  4

In [18]: df[[0]]  # ambiguous
Out[18]:
   A
0  1
1  3
Andy Hayden
źródło
2
Przepraszam, że przeszkadzam, ale tylko krótkie pytanie na ten temat. Widzę, jak to dodatkowe []sprawia, że ​​wynik jest a DataFramezamiast a Series, ale gdzie w dokumentach pandy omawia się ten rodzaj składni indeksowania? Po prostu próbuję uzyskać „oficjalną” nazwę tej techniki indeksowania, aby naprawdę ją zrozumieć. Dzięki!
sparc_spread
3
@sparc_spread pandas.pydata.org/pandas-docs/stable/indexing.html#basics "Możesz przekazać listę kolumn do [], aby wybrać kolumny w tej kolejności." Nie jestem pewien, czy to ma imię!
Andy Hayden
Tak, wygląda na to, że go nie ma - ale będę go używać od teraz. Niesamowite, ile rzeczy jest zakopanych zarówno w API, jak iw dokumentacji. Dzięki!
sparc_spread
To rozróżnienie było dla mnie przydatne, ponieważ czasami potrzebuję pojedynczej kolumny DataFrame, aby móc użyć metod DataFrame na danych, które były niedostępne w Series. (ISTR metoda fabularna zachowywała się inaczej). To było dla mnie objawienie, kiedy zdałem sobie sprawę, że mogę użyć listy jednoelementowej!
RufusVS
4

Jak zaleca Andy Hayden , najlepszym rozwiązaniem jest wykorzystanie plików .iloc / .loc do indeksowania (jednokolumnowej) ramki danych; Kolejną kwestią, na którą należy zwrócić uwagę, jest sposób wyrażania pozycji indeksu. Użyj wymienionych etykiet / pozycji indeksu podczas określania wartości argumentów do indeksowania jako Dataframe; w przeciwnym razie zostanie zwrócony plik „pandas.core.series.Series”

Wejście:

    A_1 = train_data.loc[:,'Fraudster']
    print('A_1 is of type', type(A_1))
    A_2 = train_data.loc[:, ['Fraudster']]
    print('A_2 is of type', type(A_2))
    A_3 = train_data.iloc[:,12]
    print('A_3 is of type', type(A_3))
    A_4 = train_data.iloc[:,[12]]
    print('A_4 is of type', type(A_4))

Wynik:

    A_1 is of type <class 'pandas.core.series.Series'>
    A_2 is of type <class 'pandas.core.frame.DataFrame'>
    A_3 is of type <class 'pandas.core.series.Series'>
    A_4 is of type <class 'pandas.core.frame.DataFrame'>
Sumanth Lazarus
źródło
1

Możesz użyć df.iloc[:, 0:1], w tym przypadku wynikowy wektor będzie DataFrameserią, a nie serią.

Jak widzisz:

wprowadź opis obrazu tutaj

p47hf1nd3r
źródło
1

Wspomniano o tych trzech podejściach:

pd.DataFrame(df.loc[:, 'A'])  # Approach of the original post
df.loc[:,[['A']]              # Approach 2 (note: use iloc for positional indexing)
df[['A']]                     # Approach 3

pd.Series.to_frame () to inne podejście.

Ponieważ jest to metoda, można ją zastosować w sytuacjach, w których nie ma zastosowania drugie i trzecie podejście powyżej. W szczególności jest to przydatne podczas stosowania jakiejś metody do kolumny w ramce danych i chcesz przekonwertować wynik na ramkę danych zamiast na serię. Na przykład w notatniku Jupyter seria nie będzie miała ładnych wyników, ale ramka danych będzie.

# Basic use case: 
df['A'].to_frame()

# Use case 2 (this will give you pretty output in a Jupyter Notebook): 
df['A'].describe().to_frame()

# Use case 3: 
df['A'].str.strip().to_frame()

# Use case 4: 
def some_function(num): 
    ...

df['A'].apply(some_function).to_frame()
Null_Vallue_
źródło