pandas возвращает несколько фреймов данных из функции apply

#pandas #dataframe #apply

#pandas #фрейм данных #применить

Вопрос:

РЕДАКТИРОВАТЬ на основе комментариев, уточняя примеры, чтобы изобразить более реалистичный вариант использования

Я хочу вызвать функцию с помощью df.apply. Эта функция возвращает несколько фреймов данных. Я хочу объединить каждый из этих фреймов данных в логические группы. Я не могу сделать это без использования цикла for (что противоречит цели вызова с помощью apply ).

Я пробовал вызывать функцию для каждой строки фрейма данных, и это медленнее, чем apply . Однако с помощью apply объединение результатов снова замедляет работу.

Какие-нибудь советы?

 # input data frame
data = {'Name':['Ani','Bob','Cal','Dom'], 'Age': [15,12,13,14], 'Score': [93,98,95,99]}
df_in=pd.DataFrame(data)
print(df_in)
 

Вывод>

   Name  Age  Score
0  Ani   15     93
1  Bob   12     98
2  Cal   13     95
3  Dom   14     99
 

Функция, которая будет применена>

 def func1(name, age):
    num_rows = np.random.randint(int(age/3))
    age_mul_1 = np.random.randint(low=1, high=age, size = num_rows)
    age_mul_2 = np.random.randint(low=1, high=age, size = num_rows)
    data = {'Name': [name]*num_rows, 'Age_Mul_1': age_mul_1, 'Age_Mul_2': age_mul_2}
    df_func1 = pd.DataFrame(data)
    return df_func1

def func2(name, age, score, other_params):
    num_rows = np.random.randint(int(score/10))
    score_mul_1 = np.random.randint(low=age, high=score, size = num_rows)
    data2 = {'Name': [name]*num_rows, 'score_Mul_1': score_mul_1}
    df_func2 = pd.DataFrame(data2)
    return df_func2
    
def ret_mul_df(row):
    df_A = func1(row['Name'], row['Age'])
    #print(df_A)
    
    df_B = func2(row['Name'], row['Age'], row['Score'],1)
    #print(df_B)
    return df_A, df_B
 

То, что я хочу сделать, это, по сути, создать два фрейма данных df_A_combined и df_B_combined

Однако в настоящее время я комбинирую следующим образом:

 df_out = df_in.apply(lambda row: ret_mul_df(row), axis=1)
df_A_combined = pd.DataFrame()
df_B_combined = pd.DataFrame()
for ser in df_out:
    df_A_combined = df_A_combined.append(ser[0], ignore_index=True)
    df_B_combined = df_B_combined.append(ser[1], ignore_index=True)
 
 print(df_A_combined)
Name    Age_Mul_1   Age_Mul_2
0   Ani 7   8
1   Ani 1   4
2   Ani 1   8
3   Ani 12  6
4   Bob 9   8
5   Cal 8   7
6   Cal 8   1
7   Cal 4   8
 
 print(df_B_combined)
Name    score_Mul_1
0   Ani 28
1   Ani 29
2   Ani 50
3   Ani 35
4   Ani 84
5   Ani 24
6   Ani 51
7   Ani 28
8   Bob 32
9   Cal 26
10  Cal 70
11  Dom 56
12  Dom 53
 

Как я могу избежать итерации?

Func1, func2 — это вызовы сторонних библиотек (которые требуют очень больших вычислений), и выполняется несколько таких вызовов. Также фреймы данных df_A_combined и df_B_combined не могут быть объединены между собой

Примечание: это очень упрощенный пример, и разделение функции приведет к большому количеству избыточностей.

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

1. Можете ли вы опубликовать, как будут выглядеть два последних фрейма данных? Не ясно, что вам нужно apply() здесь.

2. Зачем вам нужно несколько фреймов данных?

3. @JonathanLeon, пожалуйста, посмотрите мой улучшенный пример с двумя окончательными фреймами данных ниже. Я хочу предотвратить объединение фреймов данных в цикле for (как показано ниже), поскольку он очень тяжелый

4. Вы должны включить эту информацию в исходный вопрос. Не как «ответ»

5. @PaulH, мне нужно несколько фреймов данных, поскольку они отправляются вниз по потоку для разной обработки.

Ответ №1:

Если это не то, что вы хотите, я обновлю, если вы сможете опубликовать, как должны выглядеть два фрейма данных.

 data = {'Name':['Ani','Bob','Cal','Dom'], 'Age': [15,12,13,14], 'Score': [93,98,95,99]}
df_in=pd.DataFrame(data)
print(df_in)

df_A = df_in[['Name','Age']]
df_A['Age_Multiplier'] = df_A['Age'] * 3
print(df_A)

     ...: print(df_A)
  Name  Age  Age_Multiplier
0  Ani   15              45
1  Bob   12              36
2  Cal   13              39
3  Dom   14              42

df_B = df_in[['Name','Score']]
df_B['Score_Multiplier'] = df_B['Score'] * 2
print(df_B)

     ...: print(df_B)
  Name  Score  Score_Multiplier
0  Ani     93               186
1  Bob     98               196
2  Cal     95               190
3  Dom     99               198
 

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

1. да, мне нужны эти df_A, df_B. Как я уже упоминал, я привел очень упрощенный пример реального варианта использования. В «реальном» варианте использования только общий столбец, например, «Имя». Оставшаяся структура выглядит совсем по-другому (включая несколько строк с одинаковым именем в df_B)

2. Если вы можете опубликовать свою фактическую структуру (с фиктивными данными, если это необходимо), мы можем помочь, но на самом деле неясно, какими должны быть ваши выходные данные df.