Konwertuj ramkę danych pandy na serię

102

Jestem trochę nowy w pandach. Mam ramkę danych pandy, która ma 1 wiersz na 23 kolumny.

Chcę przekształcić to w serię? Zastanawiam się, jaki jest najbardziej pytoniczny sposób na zrobienie tego?

Próbowałem, pd.Series(myResults)ale narzeka ValueError: cannot copy sequence with size 23 to array axis with dimension 1. Nie jest wystarczająco inteligentne, aby zdać sobie sprawę, że w kategoriach matematycznych nadal jest to „wektor”.

Dzięki!

user1357015
źródło

Odpowiedzi:

67

Nie jest wystarczająco inteligentne, aby zdać sobie sprawę, że w kategoriach matematycznych nadal jest to „wektor”.

Powiedz raczej, że jest wystarczająco inteligentny, aby rozpoznać różnicę w wymiarach. :-)

Myślę, że najprostszą rzeczą, jaką możesz zrobić, jest pozycjonowanie tego wiersza za pomocą iloc, co daje serię z kolumnami jako nowym indeksem i wartościami jako wartościami:

>>> df = pd.DataFrame([list(range(5))], columns=["a{}".format(i) for i in range(5)])
>>> df
   a0  a1  a2  a3  a4
0   0   1   2   3   4
>>> df.iloc[0]
a0    0
a1    1
a2    2
a3    3
a4    4
Name: 0, dtype: int64
>>> type(_)
<class 'pandas.core.series.Series'>
DSM
źródło
2
Albo inaczej:df.T
ako
15
@ako: df.Tnie tworzy jednak serii, tylko transponowaną ramkę DataFrame.
DSM
@DSM. To prawda, df.T.iloc [0]
Antonio Andrés,
Jedynym problemem związanym z używaniem df.ilocjest to, że jeśli masz pusty df, spowoduje to podniesienie IndexError. Aby tego uniknąć, po transpozycji df użyj df.squeezemetody. Nr ref. to pandas.pydata.org/pandas-docs/stable/reference/api/…
Nicolas Fonteyne
63

Można przetransponować jednorzędową ramkę danych (co nadal skutkuje ramką danych), a następnie ścisnąć wyniki w serię (odwrotność to_frame).

df = pd.DataFrame([list(range(5))], columns=["a{}".format(i) for i in range(5)])

>>> df.T.squeeze()  # Or more simply, df.squeeze() for a single row dataframe.
a0    0
a1    1
a2    2
a3    3
a4    4
Name: 0, dtype: int64

Uwaga: Aby uwzględnić kwestię podniesioną przez @IanS (nawet jeśli nie ma jej w pytaniu OP), przetestuj rozmiar ramki danych. Zakładam, że dfjest to ramka danych, ale przypadki brzegowe to pusta ramka danych, ramka danych o kształcie (1, 1) i ramka danych z więcej niż jednym wierszem, w którym to przypadku użycie powinno zaimplementować ich pożądaną funkcjonalność.

if df.empty:
    # Empty dataframe, so convert to empty Series.
    result = pd.Series()
elif df.shape == (1, 1)
    # DataFrame with one value, so convert to series with appropriate index.
    result = pd.Series(df.iat[0, 0], index=df.columns)
elif len(df) == 1:
    # Convert to series per OP's question.
    result = df.T.squeeze()
else:
    # Dataframe with multiple rows.  Implement desired behavior.
    pass

Można to również uprościć, korzystając z odpowiedzi udzielonej przez @themachinist.

if len(df) > 1:
    # Dataframe with multiple rows.  Implement desired behavior.
    pass
else:
    result = pd.Series() if df.empty else df.iloc[0, :]
Aleksandra
źródło
11
Zauważ, że napotkałem mały problem podczas używania squeeze. W przypadku ramki danych o kształcie (1, 1)zwróci nie serię o długości 1, ale numpy skalar. Doprowadziło to do trudnego do wykrycia błędu podczas używania squeezena obiektach o nieznanej długości (np. Z groupby).
IanS
2
„Dziękuję! Df.squeeze () działało, gdy df.iloc [:, 0] i df.ix [:, 0] generowały zbyt wiele błędów indeksów”
Afflatus
4
A dlaczego jest odwrotnością to_framenie to_serieslub pd.Series(df)...?
jhin
4
Nie musisz.T
elgehelge
1
@IanS przekaż argument df.squeeze(axis=0)lub df.squeeze(axis=1)(w zależności od osi, którą chcesz zachować), aby tego uniknąć
Nicolas Fonteyne
5

Inny sposób -

Załóżmy, że myResult to dataFrame, która zawiera Twoje dane w postaci 1 kolumny i 23 wierszy

// label your columns by passing a list of names
myResult.columns = ['firstCol']

// fetch the column in this way, which will return you a series
myResult = myResult['firstCol']

print(type(myResult))

W podobny sposób możesz uzyskać serie z Dataframe z wieloma kolumnami.

Tauseef Malik
źródło
4

Możesz także użyć stack ()

df= DataFrame([list(range(5))], columns = [“a{}”.format(I) for I in range(5)])

Po uruchomieniu df uruchom:

df.stack()

Otrzymujesz swoją ramkę danych w serii

Sprytne Omo
źródło
0
data = pd.DataFrame({"a":[1,2,3,34],"b":[5,6,7,8]})
new_data = pd.melt(data)
new_data.set_index("variable", inplace=True)

Daje to ramkę danych z indeksem jako nazwą kolumny danych, a wszystkie dane są obecne w kolumnie „wartości”

user12230680
źródło
5
Witamy w Stack Overflow! Jak to odpowiada na pytanie? Twój kod nie zwraca serii, jak zadaje pytanie
Gricey