2014-04-16 12 views
25

Posiadam zdefiniowaną w następujący sposób definicję Pandas DataFrame Pandas DataFrame . (Wiem, że to nie jest najlepszy sposób, aby to zrobić, ma to sens dla tego, co próbuję zrobić w moim prawdziwym kodzie, ale to byłby TMI dla tego postu, więc uwierz mi tylko, że to podejście działa w moim konkretnym scenariuszu .)Panda DataFrame zapisana lista jako ciąg: jak przekonwertować z powrotem na listę?

>>> df = DataFrame(columns=['col1']) 
>>> df.append(Series([None]), ignore_index=True) 
>>> df 
Empty DataFrame 
Columns: [col1] 
Index: [] 

Zapisałem listy w komórkach tego DataFrame w następujący sposób.

>>> df['column1'][0] = [1.23, 2.34] 
>>> df 
    col1 
0 [1, 2] 

Z jakiegoś powodu DataFrame zapisała tę listę jako ciąg zamiast listy.

>>> df['column1'][0] 
'[1.23, 2.34]' 

Mam 2 pytania do ciebie.

  1. Dlaczego DataFrame zapisuje listę jako ciąg znaków i czy istnieje sposób obejścia tego zachowania?
  2. Jeśli nie, to czy istnieje sposób Python do konwersji tego ciągu na listę?

Aktualizacja

DataFrame używałem były zapisywane i odczytywane z formatu CSV. Ten format, a nie sama DataFrame, przekonwertował listę z ciągu znaków na literał.

+0

Czy możesz umieścić kod, który odtwarza to jako wsparcie dla ramek danych, przechowujące każdy obiekt arbritrary, więc powinno działać. – EdChum

+0

@EdChum, jasne. –

+0

Mam wersję pand w wersji '0.12.0', która nie konwertuje listy na ciąg. .. – namit

Odpowiedz

24

Jak zauważyłeś, może się to zdarzyć podczas zapisywania i wczytywania pandas DataFrames jako plików .csv, który jest formatem tekstowym.

W twoim przypadku stało się tak, ponieważ obiekty listy mają reprezentację łańcuchową, co umożliwia ich przechowywanie jako plików .csv. Ładowanie .csv spowoduje wyświetlenie tej reprezentacji ciągów znaków.

Jeśli chcesz przechowywać rzeczywiste obiekty, powinieneś użyć DataFrame.to_pickle() (uwaga: obiekty muszą być możliwe do wybrania!).

Aby odpowiedzieć na drugie pytanie, można przekonwertować go z powrotem ast.literal_eval:

>>> from ast import literal_eval 
>>> literal_eval('[1.23, 2.34]') 
[1.23, 2.34] 
+1

Pandasowe ramki danych obsługują przechowywanie dowolnych obiektów arbritrary, więc to powinno zadziałać – EdChum

+0

@EdChum Podobno nie, ponieważ mam 'list' przekonwertowane na' string' z 'to_csv', po którym następuje' from_csv' w wersji 0.17.1. –

1

tylko w celach ... pandy nie konwertować list do łańcucha. ..

In [29]: data2 = [{'a': [1, 5], 'b': 2}, {'a': 5, 'b': 10, 'c': 20}]                       

In [30]: df = pd.DataFrame(data2)                               

In [31]: df                                     
Out[31]: 
     a b c 
0 [1, 5] 2 NaN 
1  5 10 20 

In [32]: df['a'][0], type(df['a'][0])                              
Out[32]: ([1, 5], list) 

In [33]: pd.__version__ 
Out[33]: '0.12.0' 
+2

Jak odkryłem, ** czasami ** pandy konwertują listę na ciąg znaków. Musi to mieć związek ze sposobem, w jaki definiuję tę ramkę DataFrame lub wstawiam do niej dane. Dobrze wiedzieć na przyszłość. –

+0

Nie mogę ponownie utworzyć tego problemu – user1827356

+0

@ user1827356, znalazłem to! Zamierzam teraz edytować moje pytanie. –

0

Miałem ten sam problem. Podczas przechowywania kolumny listy danych do pliku CSV za pomocą df.to_csv(), kolumny listy są konwertowane na ciąg znaków, np. "[42, 42, 42]" zamiast [42, 42, 42]

Odpowiedź Alex jest poprawna i można użyć literal_eval, aby przekonwertować ciąg z powrotem na listę. Problem z tym podejściem polega na tym, że musisz zaimportować dodatkową bibliotekę i musisz zastosować lub odwzorować funkcję na swoją ramkę danych.Jako łatwiejszy sposób jest zmuszenie Pandy do zapoznania się z kolumny jako obiekt Pythona (dtype)

df["col1"].astype('O')

The O służy do obiektów Pythona w tym list. Więcej informacji here. Należy pamiętać, że ta metoda nie powiedzie się, jeśli analizować pusta lista ciągów: „[]”

Alternatywnie można również zastosować funkcję do kolumny (to jest dla liczb całkowitych):

def stringToList(string): 
    # input format : "[42, 42, 42]" , note the spaces after the commas, in this case I have a list of integers 
    string = string[1:len(string)-1] 
    try: 
     if len(string) != 0: 
      tempList = string.split(", ") 
      newList = list(map(lambda x: int(x), tempList)) 
     else: 
      newList = [] 
    except: 
     newList = [-9999] 
    return(newList) 

df["col1"] = df["col1"].apply(lambda x: stringToList(x)) 
1

Właśnie natknąłem ten problem i istnieje bardzo proste rozwiązanie (pandas.eval()). Używam pand 0.20.0.

# SETUP 
import pandas as pd 
import io 

csv = io.StringIO(u''' 
id list 
A1 [1,2] 
A2 [3,4] 
A3 [5,6] 
''') 

df = pd.read_csv(csv, delim_whitespace = True) 

# TYPE CHECK <type 'str'> 
print type(df.at[0, 'list']) 

# MAIN CONVERSION 
df['list'] = pd.eval(df['list']) 

# TYPE CHECK <type 'list'> 
print type(df.at[0, 'list']) 
Powiązane problemy