Dlaczego Pandy mówią mi, że mam obiekty, chociaż każdy element w wybranej kolumnie jest ciągiem - nawet po jawnej konwersji.
To jest moja ramka DataFrame:
<class 'pandas.core.frame.DataFrame'>
Int64Index: 56992 entries, 0 to 56991
Data columns (total 7 columns):
id 56992 non-null values
attr1 56992 non-null values
attr2 56992 non-null values
attr3 56992 non-null values
attr4 56992 non-null values
attr5 56992 non-null values
attr6 56992 non-null values
dtypes: int64(2), object(5)
Pięć z nich jest dtype object
. Jawnie konwertuję te obiekty na ciągi:
for c in df.columns:
if df[c].dtype == object:
print "convert ", df[c].name, " to string"
df[c] = df[c].astype(str)
Następnie df["attr2"]
nadal ma dtype object
, chociaż type(df["attr2"].ix[0]
ujawnia str
, co jest poprawne.
Pandy rozróżniają między int64
i float64
i object
. Jaka logika się za tym kryje, kiedy nie ma dtype str
? Dlaczego jest str
objęty gwarancją object
?
Odpowiedzi:
Obiekt dtype pochodzi z NumPy, opisuje typ elementu w ndarray. Każdy element w tablicy ndarray musi mieć ten sam rozmiar w bajtach. W przypadku int64 i float64 mają one 8 bajtów. Ale w przypadku sznurków długość sznurka nie jest ustalona. Więc zamiast zapisywać bajty łańcuchów bezpośrednio w ndarray, Pandy używają obiektu ndarray, który zapisuje wskaźniki do obiektów, z tego powodu dtype tego rodzaju ndarray to object.
Oto przykład:
źródło
Odpowiedź @ HYRY'ego jest świetna. Chcę tylko podać trochę więcej kontekstu.
Tablice przechowywać dane jak przyległe , stałej wielkości bloków pamięci. Połączenie tych właściwości razem sprawia, że tablice są błyskawiczne w dostępie do danych. Na przykład, rozważmy, jak komputer może przechowywać tablicę 32-bitowych liczb całkowitych
[3,0,1]
.Jeśli poprosisz komputer o pobranie trzeciego elementu tablicy, rozpocznie się on od początku, a następnie przeskoczy przez 64 bity, aby dotrzeć do trzeciego elementu. Wiedza dokładnie, przez ile bitów przeskoczyć, sprawia, że tablice są szybkie .
Teraz rozważ sekwencję ciągów
['hello', 'i', 'am', 'a', 'banana']
. Łańcuchy to obiekty o różnej wielkości, więc jeśli spróbujesz zapisać je w ciągłych blokach pamięci, skończy się to tak.Teraz twój komputer nie ma szybkiego dostępu do losowo żądanego elementu. Kluczem do przezwyciężenia tego jest użycie wskaźników. Zasadniczo przechowuj każdy ciąg w jakiejś losowej lokalizacji pamięci i wypełnij tablicę adresem pamięci każdego ciągu. (Adresy pamięci to tylko liczby całkowite). Więc teraz wygląda to tak
Teraz, jeśli poprosisz komputer o pobranie trzeciego elementu, tak jak poprzednio, może przeskoczyć przez 64 bity (zakładając, że adresy pamięci są 32-bitowymi liczbami całkowitymi), a następnie wykonać jeden dodatkowy krok, aby pobrać ciąg.
Wyzwaniem dla NumPy jest to, że nie ma gwarancji, że wskaźniki faktycznie wskazują na ciągi. Dlatego zgłasza typ dtype jako „obiekt”.
Bezwstydnie podłączę własny artykuł na blogu, w którym pierwotnie o tym dyskutowałem.
źródło
Przyjęta odpowiedź jest dobra. Chciałem tylko udzielić odpowiedzi, która odnosiła się do dokumentacji . Dokumentacja mówi:
Jak mówi główny komentarz: „Nie martw się o to, tak powinno być”. (Chociaż zaakceptowana odpowiedź świetnie się spisała, wyjaśniając „dlaczego”; ciągi znaków mają zmienną długość)
źródło
astype(str)
mimo to wciąż konwersja dziwnego ciąg jest koniecznePocząwszy od wersji 1.0.0 (styczeń 2020 r.), Pandy zostały wprowadzone jako funkcja eksperymentalna zapewniająca pierwszorzędną obsługę typów ciągów poprzez
pandas.StringDtype
.Choć nadal będziesz widzieć
object
domyślnie nowego typu mogą być wykorzystywane przez podaniedtype
odpd.StringDtype
lub po prostu'string'
:>>> pd.Series(['abc', None, 'def']) 0 abc 1 None 2 def dtype: object >>> pd.Series(['abc', None, 'def'], dtype=pd.StringDtype()) 0 abc 1 <NA> 2 def dtype: string >>> pd.Series(['abc', None, 'def']).astype('string') 0 abc 1 <NA> 2 def dtype: string
źródło
The implementation may change without warning.
co oznacza , że nowe aktualizacje zepsują stare programy.