#python-3.x
Вопрос:
У меня есть фрейм данных с именем new_data
, содержащий два списка столбцов :
l = ["l_1stIn","l_1stWon", "l_2ndWon","l_ace", "l_bpFaced","l_df","l_age","l_rank_gap","l_rank_points","l_1stIn"]
w = ["w_1stIn","w_1stWon", "w_2ndWon","w_ace", "w_bpFaced","w_df", "w_age","w_rank_gap","w_rank_points","w_1stIn"]
Я хочу создать новый фрейм данных с новыми столбцами, которые являются результатом разницы между
двумя списками столбцов, указанными ниже :
loss['1stIn'] = new_data.apply(lambda x: f(x.l_1stIn, x.w_1stIn), axis=1)
loss['1stWon'] = new_data.apply(lambda x: f(x.l_1stWon, x.w_1stWon), axis=1)
loss['2ndWon'] = new_data.apply(lambda x: f(x.l_2ndWon, x.w_2ndWon), axis=1)
loss['ace'] = new_data.apply(lambda x: f(x.l_ace, x.w_ace), axis=1)
loss['bpFaced'] = new_data.apply(lambda x: f(x.l_bpFaced, x.w_bpFaced), axis=1)
loss['df'] = new_data.apply(lambda x: f(x.l_df, x.w_df), axis=1)
loss['age'] = new_data.apply(lambda x: f(x.l_age, x.w_age), axis=1)
loss['ht'] = new_data.apply(lambda x: f(x.l_ht, x.w_ht), axis=1)
loss['rank_gap'] = new_data.apply(lambda x: f(x.l_rank_gap, x.w_rank_gap), axis=1)
loss['rank_points'] = new_data.apply(lambda x: f(x.l_rank_points, x.w_rank_points), axis=1)
loss['1stIn'] = new_data.apply(lambda x: f(x.l_1stIn, x.w_1stIn), axis=1)
Итак, я хочу создать новый loss
фрейм данных, как указано ниже, но без многократного повторения функции apply. Я ищу общую функцию, которая имеет в качестве входных данных три списка :
l = ["l_1stIn","l_1stWon", "l_2ndWon","l_ace", "l_bpFaced","l_df","l_age","l_rank_gap","l_rank_points","l_1stIn"]
w = ["w_1stIn","w_1stWon", "w_2ndWon","w_ace", "w_bpFaced","w_df","w_age","w_rank_gap","w_rank_points","w_1stIn"]
output = ["1stIn","1stWon", "2ndWon","ace",
"bpFaced","df","age", "rank_gap","rank_points","1stIn"]
и возвращает конечный фрейм данных loss
output
, содержащий столбцы as, который является результатом разницы между l
и w
Комментарии:
1. Написать такую функцию не так уж сложно. Вы знаете , что вы можете получить доступ к столбцам фрейма данных с помощью обозначения индекса: когда вы это сделаете
col = "l_1stIn"
, вамdf[col]
будет предоставлен этот столбец фрейма данных. Теперь примените эту идею к каждому новому столбцу, который вы хотите. Как только вы попытаетесь, задайте конкретный вопрос о своем коде.2. @PranavHosangadi, я новичок в python, и я ищу решение для оптимизации, чтобы избежать повторения каждый раз. Я посмотрю, как это можно сделать, используя индекс, как вы предложили. Спасибо вам в любом случае
Ответ №1:
Вы можете определить функцию, которая будет принимать пару столбцов и возвращать вывод столбца следующим образом:
def do_calculation(col0, col1):
# Do something with both columns and then return the result
# For example,
return col0 - col1
Затем давайте напишем функцию, которая будет принимать множество входных и выходных столбцов и вызывать doCalculation()
их с правильными входными данными.
def process_data(func, data, inputs_0, inputs_1, outputs):
df = pd.DataFrame()
# zip to iterate over all three lists together
for col_in0, col_in1, col_out in zip(inputs_0, inputs_1, outputs):
in0 = data[col_in0] # Get the first input col
in1 = data[col_in1] # Second input col
df[col_out] = func(in0, in1) # Call the given func and set its output as the output column
return df
И, наконец, давайте создадим фиктивный фрейм данных и вызовем эту функцию:
В моем фрейме данных каждая строка описывает банковский счет и содержит четыре столбца: Предыдущий баланс , сумма для списания, возраст владельца на данный момент и возраст владельца на момент открытия счета. Мы собираемся рассчитать текущий баланс и количество лет, в течение которых они держали счет.
import io
csvtext="""old_balance,debit_amount,age_current,age_start
100,20,50,45
500,10,30,10
200,100,80,30"""
in_df = pd.read_csv(io.StringIO(csvtext)) # Read the dataframe
old_balance debit_amount age_current age_start
0 100 20 50 45
1 500 10 30 10
2 200 100 80 30
Если бы вы делали это, используя свой метод, вы бы сделали:
df = pd.DataFrame()
df['new_balance'] = in_df.apply(lambda x: x.old_balance - x.debit_amount, axis=1)
df['customer_for'] = in_df.apply(lambda x: x.age_current - x.age_start, axis=1)
что дает:
new_balance customer_for
0 80 5
1 490 20
2 100 50
Чтобы вызвать нашу функцию, нам нужно предоставить ей функцию, которая выполняет вычисления, входные данные, входные столбцы
inputs_0 = ["old_balance", "age_current"]
inputs_1 = ["debit_amount", "age_start"]
outputs = ["new_balance", "customer_for"]
df = process_data(do_calculation, in_df, inputs_0, inputs_1, outputs)
Результат этого такой же, как и в предыдущем коде, без всех этих повторений.
Комментарии:
1. спасибо за это решение, но я получил эту ошибку :
NameError: name 'col_in0' is not defined
2. @Rпрограммист Ой, опечатка. Измените строку на
for col_in0, col_in1, col_out in zip(inputs_0, inputs_1, outputs):
3. Я пытался
for col_in0, col_in1, col_out in zip(inputs_0, inputs_1, outputs):
, но ни за что4. Что ты имеешь в виду? Я обновил код в своем ответе, чтобы исправить эту опечатку.