#python #pandas #dataframe #for-loop #if-statement
Вопрос:
У меня есть фрейм данных, который выглядит так…
Variable
0 Religion - Buddhism
1 Source: Clickerz
2 Religion - Islam
3 Source: SRZ FREE
4 Ethnicity - Mixed - White amp; Black African
Я хочу манипулировать variable
столбцом, чтобы создать такой new column
, который выглядит следующим образом…
Variable New Column
0 Religion - Buddhism Buddhism
1 Source: Clickerz Clickerz
2 Religion - Islam Islam
3 Source: SRZ FREE SRZ FREE
4 Ethnicity - Mixed - White amp; Black African Mixed - White and Black African
Чтобы в конечном итоге у меня был фрейм данных, который выглядит так…
Variable New Column
0 Religion Buddhism
1 Source Clickerz
2 Religion Islam
3 Source SRZ FREE
4 Ethnicity Mixed - White and Black African
Я хочу выполнить итерацию по Variable
столбцу и манипулировать данными для создания New Column
. Я планировал использовать несколько if
операторов, чтобы найти определенное слово, например 'Ethnicity'
, или 'Religion'
, а затем применить манипуляцию.
Например…
For row in df['Variable']:
if 'Religion' in row:
df['New Column'] = ...
elif 'Ethnicity' in row:
df['New Column'] = ...
elif: 'Source' in row:
df['New Column'] = ...
else:
df['New Column'] = 'Not Applicable'
Несмотря type(row)
на то, что возвращает 'str'
значение, относящееся к строке класса, этот код продолжает возвращать новый столбец как «Неприменимый», что означает, что он не обнаруживает ни одной строки ни в одной из строк во фрейме данных, даже когда я вижу, что они там есть.
Я уверен, что есть простой способ сделать это…ПОЖАЛУЙСТА, ПОМОГИТЕ!
Я также попробовал следующее…
For row in df['Variable']:
if row.find('Religion') != -1:
df['New Column'] = ...
elif row.find('Ethnicity') != -1:
df['New Column'] = ...
elif: row.find('Source') != -1:
df['New Column'] = ...
else:
df['New Column'] = 'Not Applicable'
И я продолжаю получать все записи в новой колонке «Неприменимо». И снова он не находит строку в существующем столбце.
Это проблема с типом данных или что-то в этом роде?
Ответ №1:
Вы могли бы использовать вложенный for
цикл:
# For each row in the dataframe
for row in df['column_variable']:
# Set boolean to indicate if a substring was found
substr_found = False
# For each substring
for sub_str in ["substring1", "substring2"]:
# If the substring is in the row
if sub_str in row:
# Execute code...
df['new_column'] = ...
# Substring was found!
substr_found = True
# If substring was not found
if not substr_found:
# Set invalid code...
df['new column'] = 'Not Applicable'
Ответ №2:
Насколько это возможно, вам следует избегать зацикливания строк при работе с a DataFrame
. В этой статье объясняется, какие альтернативы являются более эффективными.
Вы в основном пытаетесь перевести строки на основе некоторой фиксированной карты. Естественно, dict
на ум приходит а:
substring_map = {
"at": "pseudo-cat",
"dog": "true dog",
"bre": "something else",
"na": "not applicable"
}
Эту карту можно прочитать из файла, например файла JSON, в сценарии, где вы обрабатываете большое количество подстрок.
Логику сопоставления подстрок теперь можно отделить от определения карты:
def translate_substring(x):
for substring, new_string in substring_map.items():
if substring in x:
return new_string
return "not applicable"
Используйте apply
функцию «сопоставление» для создания целевого столбца:
df = pd.DataFrame({"name":
["cat", "dogg", "breeze", "bred", "hat", "misty"]})
df["new_column"] = df["name"].apply(translate_substring)
# df:
# name new_column
# 0 cat pseudo-cat
# 1 dogg true dog
# 2 breeze something else
# 3 bred something else
# 4 hat pseudo-cat
# 5 misty not applicable
Этот код, примененный к pd.concat([df] * 10000)
(60 000 строк), выполняется за 42 мс в записной книжке Colab. Для сравнения, использование iterrows
завершается за 3,67 с-ускорение в 87 раз.
Ответ №3:
Вы можете создать пустой список, добавить туда новые значения и создать новый столбец в качестве последнего шага:
all_data = []
for row in df["column_variable"]:
if "substring1" in row:
all_data.append("Found 1")
elif "substring2" in row:
all_data.append("Found 2")
elif "substring3" in row:
all_data.append("Found 3")
else:
all_data.append("Not Applicable")
df["new column"] = all_data
print(df)
С принтами:
column_variable new column
0 this is substring1 Found 1
1 this is substring2 Found 2
2 this is substring1 Found 1
3 this is substring3 Found 3
Комментарии:
1. По какой-то причине, когда я набираю…»если» подстрока «в строке:» она не находит подстроку в строке, даже если она явно там. Это и есть главная проблема
2. @ElliottDavey Пожалуйста, отредактируйте свой вопрос с помощью образца вашего фрейма данных.
Ответ №4:
Может быть, самый короткий путь, который я могу придумать:
#Dummy DataFrame
df = pd.DataFrame([[1,"substr1"],[3,"bla"],[5,"bla"]],columns=["abc","col_to_check"])
substrings = ["substr1","substr2", "substr3"]
content = df["col_to_check"].unique().tolist() # Unique content of column
for subs in substrings: # Go through all your substrings
if subs in content: # Check if substring is in column
df[subs] = 0 # Fill your new column with whatever you want
Ответ №5:
Обновлено в соответствии с вашим фреймом данных!
import pandas as pd
Ваш Фрейм данных
lst = []
for i in ['Religion - Buddhism','Source: Clickerz','Religion - Islam','Source: SRZ FREE','Ethnicity - Mixed - White amp; Black African']:
item = [i]
lst.append(item)
df = pd.DataFrame.from_records(lst)
df.columns = ['variable']
print(df)
variable
0 Religion - Buddhism
1 Source: Clickerz
2 Religion - Islam
3 Source: SRZ FREE
4 Ethnicity - Mixed - White amp; Black African
Использование цикла For и частичного сопоставления строк в сочетании с .loc
установкой новых значений
for x,y in df['variable'].iteritems():
if 'religion' in y.lower():
z = y.split('-')
df.loc[x, 'variable'] = z[0].strip()
df.loc[x, 'value'] = ''.join(z[1:]).strip()
if 'source' in y.lower():
z = y.split(':')
df.loc[x, 'variable'] = z[0].strip()
df.loc[x, 'value'] = ''.join(z[1:]).strip()
if 'ethnicity' in y.lower():
z = y.split('-')
df.loc[x, 'variable'] = z[0].strip()
df.loc[x, 'value'] = ''.join(z[1:]).strip()
print(df)
variable value
0 Religion Buddhism
1 Source Clickerz
2 Religion Islam
3 Source SRZ FREE
4 Ethnicity Mixed White amp; Black African
Ответ №6:
Я создал функцию «string_splitter» и применил ее в лямбда-функции, это решило проблему.
Я создал следующую функцию для разделения строк различными способами на основе разных подстрок, содержащихся в ячейке.
def string_splitter(cell):
word_list1 = ['Age', 'Disability', 'Religion', 'Gender']
word_list2 = ['Number shortlisted', 'Number Hired', 'Number Interviewed']
if any([word in cell for word in word_list1]):
result = cell.split("-")[1]
result = result.strip()
elif 'Source' in cell:
result = cell.split(":")[1]
result = result.strip()
elif 'Ethnicity' in cell:
result_list = cell.split("-")[1:3]
result = "-".join(result_list)
result = result.strip()
elif any([word in cell for word in word_list2]):
result = cell.split(" ")[1]
result = result.strip()
elif 'Number of Applicants' in cell:
result = cell
return result
Затем я позвонил string_splitter
при использовании лямбда-операции. Это применяло функцию к каждой ячейке по отдельности, поскольку код повторяется по каждой строке указанного столбца в фрейме данных. Как показано ниже:
df['Answer'] = df['Visual Type'].apply(lambda x: string_splitter(x))
string_splitter
позволил мне создать New column
свое .
Затем я создал другую функцию column_formatter
для управления Variable
столбцом после New Column
того, как он был создан. Вторая функция показана ниже:
def column_formatter(cell):
word_list1 = ['Age', 'Gender', 'Ethnicity', 'Religion']
word_list2 = ['Number of Applicants', 'Number Hired', 'Number shortlisted', 'Number Interviewed']
if any([word in cell for word in word_list1]):
result = cell.split("-")[0]
result = result.strip()
elif 'Source' in cell:
result = cell.split(":")[0]
result = result.strip()
elif 'Disability' in cell:
result = cell.split(" ")[0]
result = result.strip()
elif any([word in cell for word in word_list2]):
result = 'Number of Applicants'
else:
result = 'Something wrong here'
return result
А затем вызвал функцию таким же образом, как показано ниже:
df['Visual Type'] = df['Visual Type'].apply(lambda x: column_formatter(x))