Панды ищут подстроку, а затем пишут в другой

#python #pandas #dataframe

Вопрос:

Поэтому я пытаюсь найти частичную строку в определенном столбце моего csv-файла. Если это соответствует определенному условию, он напишет что-то еще в другой колонке.

Например:

 Letter Grade Percentage  A Ninety Five Percent  C Seventy Three Percent  B Eighty Two Percent  

Столбец «Процент» всегда будет иметь один и тот же формат «Девяносто пять процентов», то есть число в словах Процент.

Я хочу, чтобы можно было открыть файл csv, чтобы python проанализировал столбец процентов для первого слова, например, если он содержит «Девяносто», то он назначит «А» в столбце «класс букв», если он содержит «Восемьдесят», затем » Б » в классе букв и так далее, и так далее.

Это мой текущий код:

 import pandas as pd  df = pd.DataFrame(pd.read_csv(r'file.csv', dtype=str))  A = 'Ninety' B = 'Eighty' C = 'Seventy' D = 'Sixty'  if df[df['Percentage'].isin(A)]:  df['Letter Grade'] = df['Letter Grade'].str.replace['', 'A', regex=False] elif df[df['Percentage'].isin(B)]:  df['Letter Grade'] = df['Letter Grade'].str.replace['', 'B', regex=False] elif df[df['Percentage'].isin(C)]:  df['Letter Grade'] = df['Letter Grade'].str.replace['', 'C', regex=False] elif df[df['Percentage'].isin(D)]:  df['Letter Grade'] = df['Letter Grade'].str.replace['', 'D', regex=False] else:  df['Letter Grade'] = df['Letter Grade'].str.replace['', 'F', regex=False]   df.to_csv(r'file.csv', index=False)  

В настоящее время он выдает мне эту ошибку: The truth value of a DataFrame is ambiguous.

Ответ №1:

Вы можете использовать dictionary split map для этого функцию и

 grades={'Ninety':'A', 'Eighty':'B', 'Seventy':'C', 'Sixty':'D'}  df['Letter Grade'] = df.Percentage.str.split(expand=True)[0].map(grades)  

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

1. если это ваше решение, то примите его как ответ. Спасибо

Ответ №2:

Попробуйте с numpy.select :

 import numpy as np  df["Letter Grade"] = np.select([df["Percentage"].str.contains(A),  df["Percentage"].str.contains(B),   df["Percentage"].str.contains(C),  df["Percentage"].str.contains(D)],   ["A","B","C","D"])  

Альтернативно с findall и map :

 mapper = {"Ninety": "A", "Eighty": "B", "Seventy": "C", "Sixty": "D"} df["Letter Grade"] = df["Percentage"].str.findall("|".join(mapper.keys())).str[0].map(mapper)  

Ответ №3:

ответ @not_speshal великолепен, но на самом деле он не объясняет точную проблему, с которой вы столкнулись.

isin фактически возвращает фрейм данных с перечислением каждого столбца и независимо от того, была ли строка найдена как целый элемент (например, он найдет 'Ninenty' , но не «Девять x»).

Вместо этого вы можете использовать .str.contains(...) столбец, который вернет копию столбца, в котором находится каждый элемент True , если строка в столбцах содержала вашу строку, False в противном случае. Затем вы можете вызвать .any() результирующую серию , которая вернется True , если в серии есть один элемент True , и она вернется False , если в True серии нет значений (не было совпадающих строк).

Вместо

 if df[df['Percentage'].isin(A)]:  

ты хочешь:

 if df['Percentage'].str.contains('Ninety').any():