web-dev-qa-db-ja.com

Pandas文字列としてのDataFrame保存リスト:リストに戻す方法は?

私はn-by-mPandas DataFrame dfは次のように定義されています(これが最善の方法ではないことはわかっています。実際のコードでやろうとしていることには意味がありますが、それはTMIになりますこの投稿では、このアプローチが私の特定のシナリオで機能するように、私の言葉を引用してください。)

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

次のように、このDataFrameのセルにリストを保存しました。

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

何らかの理由で、DataFrameはこのリストをリストではなく文字列として保存しました。

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

2つの質問があります。

  1. なぜDataFrameはリストを文字列として保存し、この動作を回避する方法があるのですか?
  2. そうでない場合、この文字列をリストに変換するPythonの方法はありますか?

更新

私が使用していたDataFrameは保存され、CSV形式から読み込まれました。 この形式は、DataFrame自体ではなく、リストを文字列からリテラルに変換しました。

38
Gyan Veda

あなたが指摘したように、これは一般にpandas DataFramesを_.csv_ファイルとして保存およびロードするときに起こります。これはテキスト形式です。

あなたの場合、これはリストオブジェクトが_.csv_ファイルとして保存できる文字列表現を持っているために起こりました。 _.csv_をロードすると、その文字列表現が生成されます。

実際のオブジェクトを保存したい場合は、DataFrame.to_pickle()を使用する必要があります(注:オブジェクトはpickle可能でなければなりません!)。

2番目の質問に答えるには、 _ast.literal_eval_ で元に戻すことができます:

_>>> from ast import literal_eval
>>> literal_eval('[1.23, 2.34]')
[1.23, 2.34]
_
46
Alex Thornton

この問題に出会ったばかりで、非常に簡単な解決策があります( pandas.eval() )。私はpandas 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'])
4
elPastor

1)この動作を回避する方法があります。ここでlocを使用してください。

>>> import pandas as pd

>>> df = pd.DataFrame(columns=['column1'])
>>> df = df.append(pd.Series(data = {'column1':[None]}), ignore_index = True)

   column1
0  [None]

>>> # Add list to index 0 in column1
>>> df.loc[0,'column1'] = [1.23, 2.34]
>>> print(df.loc[0, 'column1'])
[1.23, 2.34]

2)この文字列をリストに変換するPythonの方法。 (これはおそらく、使用しているDataFrameがCSV形式から保存およびロードされていたために必要なものです。これにはいくつかの解決策があります)。これはpshep123の回答に追加されたものです。

from ast import literal_eval
import pandas as pd

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

# Output is a string
df.loc[0, 'list']
'[1,2]'

# Convert entire column to a list
df.loc[:,'list'] = df.loc[:,'list'].apply(lambda x: literal_eval(x))

# Output is a list
df.loc[0, 'list']
[1, 2]

同じ問題がありました。 df.to_csv()を使用してデータフレームリストの列をCSVファイルに保存すると、リストの列は文字列に変換されます。 [42、42、42]の代わりに「[42、42、42]」

アレックスの答えは正解で、_literal_eval_を使用して文字列をリストに戻すことができます。このアプローチの問題は、追加のライブラリをインポートする必要があり、関数をデータフレームに適用またはマップする必要があることです。簡単な方法は、Pandasとして列をPython object(dtype)

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

OはPythonリストを含むオブジェクト。詳細情報 ここ に使用されます。空のリスト文字列を解析する場合、このメソッドは失敗することに注意してください: "]

または、関数を列に適用することもできます(これは整数用です):

_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
Rutger Hofste

参照のみ... pandasリストを文字列に変換しないでください。

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'
1
namit

pandas-
df = pd.read_csv(df_name, converters={'column_name': eval})

これは、その列を文字列の代わりにpythonの対応するdtypeとして読み取ります。

0
markroxor

私が使用した簡単なハックは、最初と最後の要素(str形式のリストブラケット)のインデックスを作成するラムダ関数を呼び出し、リスト要素をintに置き換える別のメソッドが続くsplitメソッドを呼び出します。

df['column1'] = df['column1'].apply(lambda x:x[1:-1].split(',')).apply(lambda x:[int(i) for i in x])
0
Hassen Morad