programing

Panda DataFrame은 다음 문자열로 목록을 저장했습니다.목록으로 다시 변환하는 방법

newsource 2023. 4. 10. 21:58

Panda DataFrame은 다음 문자열로 목록을 저장했습니다.목록으로 다시 변환하는 방법

n-by-m Panda Data Frame을 가지고 있습니다.df다음과 같이 정의됩니다.(이 방법이 최선책이 아니라는 것을 알고 있습니다.실제 코드로 무엇을 하려고 하는지는 이해가 되지만, 이 투고에서는 TMI가 되기 때문에, 이 어프로치는 특정의 시나리오에서 유효하게 됩니다).

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

저는 이 Data Frame의 셀에 다음과 같이 리스트를 저장했습니다.

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

어떤 이유로 DataFrame은 이 목록을 목록이 아닌 문자열로 저장했습니다.

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

두 가지 질문이 있습니다.

  1. Data Frame은 왜 목록을 문자열로 저장하며 이 동작을 회피하는 방법이 있습니까?
  2. 그렇지 않다면 이 문자열을 목록으로 변환할 수 있는 피토닉 방법이 있습니까?

갱신하다

사용하던 Data Frame은 CSV 형식으로 저장 및 로딩되어 있었습니다.DataFrame 자체가 아닌 이 형식은 목록을 문자열에서 리터럴로 변환했습니다.

지적하신 바와 같이 팬더 DataFrames를 다음과 같이 저장하고 로드할 때 일반적으로 발생할 수 있습니다..csv파일(텍스트 형식)을 지정합니다.

이 문제는 목록 객체에 문자열이 표시되므로 다음과 같이 저장할 수 있기 때문에 발생합니다..csv파일 로드.csv그러면 문자열이 표시됩니다.

실제 개체를 저장하려면 다음 명령을 사용해야 합니다.DataFrame.to_pickle()(주의: 객체는 선택 가능해야 합니다!)

두 번째 질문에 답하려면 다음과 같이 다시 변환할 수 있습니다.

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

판다를 직접 이용할 수 있다-

import pandas as pd
df = pd.read_csv(DF_NAME, converters={'COLUMN_NAME': pd.eval})

이 컬럼은 문자열 대신 python에서 대응하는 dtype으로 읽힙니다.

갱신:

@ctwardy가 댓글로 지적한 바와 같이.사용하는 것이 현명하다pd.eval대신eval의도하지 않은 regex 관련 결과를 방지하기 위해 사용됩니다.상세 - https://realpython.com/python-eval-function/ #security-of-valuation

  • Python 리터럴 또는 컨테이너 데이터 형식을 포함하는 문자열을 안전하게 평가하는 데 사용합니다.
    • 표준 라이브러리의 일부입니다.

    • python's eval() vs. ast.literal_eval()사용하면 그 이유를 알 수 있습니다.literal_eval사용하는 것보다 안전합니다.eval.

    • 예:

      • literal_eval("[1.23, 2.34]")작동하다
      • literal_eval("['KB4523205','KB4519569','KB4503308']")작동하다
        • 다른 답변에서는 를 언급하고 있습니다만, 그 사용법은 한정되어 있습니다.ValueError: NumExpr 2 does not support Unicode as a dtype.이 간단한 예시를 위해.
      • literal_eval("[KB4523205, KB4519569, KB4503308]")동작하지 않는다(주변에 견적 없음)str값)
  • 는 열 변환하기 '열 변환'을 합니다.converters의 파라미터입니다.

test.csv

col1
"[1.23, 2.34]"
"['KB4523205','KB4519569','KB4503308']"

csv를 생성할 때 열 변환

from ast import literal_eval
import pandas as pd

# convert the column during import
df = pd.read_csv('test.csv', converters={'col1': literal_eval})

# display(df)
                                col1
0                       [1.23, 2.34]
1  [KB4523205, KB4519569, KB4503308]

# check type
print(type(df.iloc[0, 0]))
list

print(type(df.iloc[1, 0]))
list

기존 데이터 프레임의 열을 변환합니다.

df.col1 = df.col1.apply(literal_eval)

%%timeit

  • pd.eval literal_eval
  • 의 「」test.csv의 2,820,511 의 with"[1.23, 2.34]"

여기에 이미지 설명 입력

방금 이 문제를 발견했는데 매우 간단한 해결책(pandas.eval())이 있습니다.팬더 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'])

1) 이 행동을 회피하는 방법이 있습니다.loc help를 사용합니다.

>>> 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) 이 문자열을 목록으로 변환하는 피토닉 방식.(사용하는 Data Frame은 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_csvflist 목록을 사용하여 CSV 파일에 데이터 프레임목록 열을 저장하는 경우 [42, 42, 42]가 아닌 문자열로 변환됩니다.

이고 알렉스를 해도 됩니다.사용할 수 있습니다.literal_eval이치노이 접근방식의 문제는 추가 라이브러리를 Import하고 함수를 데이터 프레임에 적용 또는 매핑해야 한다는 것입니다.보다 쉬운 방법은 Panda가 Python 객체로 칼럼을 읽도록 강제하는 것입니다(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))

참고용으로만...판다는 목록을 끈으로 바꾸지 않는다.

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'

제가 사용한 간단한 해킹은 lambda 함수를 호출하는 것입니다.이 함수는 처음과 마지막 요소(str 형식의 목록 괄호)를 인덱스 아웃하고 다음으로 분할 메서드를 호출한 후 목록 요소를 int로 대체하는 것입니다.

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

알렉스의 대답에 더해서.다음은 개별 항목을 문자열에서 목록으로 변환하는 데 사용할 수 있는 다른 버전입니다.

import pandas as pd
from ast import literal_eval

df = pd.read_csv("some_csvfile.csv")

def item_gen(l):
    for i in l:
        yield(i)

for i in item_gen(df["some_column_with_list_item"]):
    print(literal_eval(i))

언급URL : https://stackoverflow.com/questions/23111990/pandas-dataframe-stored-list-as-string-how-to-convert-back-to-list