Pandas: преобразовать определенный столбец str в список в качестве других значений

#python-3.x #pandas #dataframe #python-3.6

#python-3.x #pandas #фрейм данных #python-3.6

Вопрос:

У меня есть столбец фрейма данных pandas, который содержит оба list str значения и . Я только пытаюсь преобразовать str значения в правильный list формат, чтобы он соответствовал другим list значениям формы. Я нашел исправление, но я хочу посмотреть, есть ли лучший способ сделать это? Ниже приведены мои вопросы:

  1. Если есть функциональность / возможность сборки pandas для использования вместо записи long regex , replace , ..etc?
  2. Как преобразовать [nan] в [] без регулярных выражений?

Вот моя попытка:

Файл данных:

 StudentName,CourseID
Alan,"['abc-12-0878', 'abc-12-45', 'abc-12-232342']"
Tim,"['abc-12-0878', 'abc-12-45']"
David,abc-12-1147
Martha,
Matt,"['abc-12-0878', 'abc-12-45']"
Abby,abc-12-1148
  

Мой код пытается:

 import pandas as pd

df = pd.read_csv('sample_students.csv')
df


df['result'] = df['CourseID'].astype(str).apply(lambda x: x.strip('[]').replace("'","").split(',')) 
# Regex route.
# Pandas`s build in function available?
# gives `[nan]` instead of `[]`
# `to_list` and `tolist` didn't work.
  

Результат, который я ищу:

 print(df[['CourseID','result']]) 

CourseID                                        result
['abc-12-0878', 'abc-12-45', 'abc-12-232342']   ['abc-12-0878', 'abc-12-45', 'abc-12-232342']
['abc-12-0878', 'abc-12-45']                    ['abc-12-0878', 'abc-12-45']
abc-12-1147                                     ['abc-12-1147']
NaN                                             []
['abc-12-0878', 'abc-12-45']                    ['abc-12-0878', 'abc-12-45']
abc-12-1148                                     [abc-12-1148]
  

Ответ №1:

Вы можете применить ast.literal_eval() для синтаксического анализа буквального представления списка.

 import ast

def f(s):
    if pd.isna(s):     # case 1: nan
        return []
    elif s[0] == "[":  # case 2: string of list
        return ast.literal_eval(s)
    else:              # case 3: string
        return [s]

df["result"] = df["CourseID"].apply(f)
  

Или в однострочном:

 df["result"] = df["CourseID"].apply(lambda s: [] if pd.isna(s) else ast.literal_eval(s) if s[0] == "[" else [s])
  

Результат:

 print(df[["CourseID","result"]])
                                        CourseID                                   result
0  ['abc-12-0878', 'abc-12-45', 'abc-12-232342']  [abc-12-0878, abc-12-45, abc-12-232342]
1                   ['abc-12-0878', 'abc-12-45']                 [abc-12-0878, abc-12-45]
2                                    abc-12-1147                            [abc-12-1147]
3                                            NaN                                       []
4                   ['abc-12-0878', 'abc-12-45']                 [abc-12-0878, abc-12-45]
5                                    abc-12-1148                            [abc-12-1148]
  

Ответ №2:

Если вы предпочитаете не импортировать другую библиотеку, вы можете сделать это следующим образом:

 def update_data(val):
    if pd.isna(val):
        return []
    if val[0] == '[':
        return val    
    return [val]
df['Result'] = df.apply(lambda row: update_data(row['CourseID']), axis= 1)
  

Ответ №3:

Вы можете проверить только тип значения

 df['result'] = df['CourseID'].apply(lambda x: x.strip('[]').replace("'","").split(',') if type(x) == str else [])
  
 >>> print(df[['CourseID','result']])
                                        CourseID                                     result
0  ['abc-12-0878', 'abc-12-45', 'abc-12-232342']  [abc-12-0878,  abc-12-45,  abc-12-232342]
1                   ['abc-12-0878', 'abc-12-45']                  [abc-12-0878,  abc-12-45]
2                                    abc-12-1147                              [abc-12-1147]
3                                            NaN                                         []
4                   ['abc-12-0878', 'abc-12-45']                  [abc-12-0878,  abc-12-45]
5                                    abc-12-1148                              [abc-12-1148]
  

Комментарии:

1. Я не проверял, что происходит, когда идентификатор курса равен и является целым или плавающим