Комбинируйте 2 pandas dataframes в соответствии с булевым вектором

Моя проблема заключается в следующем:
Скажем, у меня есть два кадра данных с таким же количеством столбцов в pandas, как например:

A= 1 2
   3 4 
   8 9

и

B= 7 8
   4 0

А также один логический вектор длины точно из нескольких строк из A + num из строк B = 5, с таким же числом 1, что и число строк в B, что означает два 1 в этом примере. Скажем Bool= 0 1 0 1 0.

Моя цель состоит в том, чтобы объединить A и B в более крупный фрейм данных C, чтобы строки B соответствовали 1s в Bool, поэтому в этом примере это дало бы мне:

C= 1 2
   7 8
   3 4 
   4 0
   8 9

Вы знаете, как это сделать, пожалуйста? Если вы знаете, как это мне очень поможет. Спасибо за ваше чтение.

Ответ 1

Один из вариантов - создать пустой фрейм данных с ожидаемой формой, а затем заполнить значения из A и B в:

import pandas as pd
import numpy as np

# initialize a data frame with the same data types as A thanks to @piRSquared
df = pd.DataFrame(np.empty((A.shape[0] + B.shape[0], A.shape[1])), dtype=A.dtypes)
Bool = np.array([0, 1, 0, 1, 0]).astype(bool)

df.loc[Bool,:] = B.values
df.loc[~Bool,:] = A.values

df
#   0   1
#0  1   2
#1  7   8
#2  3   4
#3  4   0
#4  8   9

Ответ 2

Здесь pandas -одно решение, которое переиндексирует исходные фреймы данных и затем объединяет их:

Bool = pd.Series([0, 1, 0, 1, 0], dtype=bool) 
B.index = Bool[ Bool].index
A.index = Bool[~Bool].index
pd.concat([A,B]).sort_index() # sort_index() is not really necessary
#   0  1
#0  1  2
#1  7  8
#2  3  4
#3  4  0
#4  8  9

Ответ 3

Следующий подход будет обобщен на более крупные группы, чем 2. Начиная с

A = pd.DataFrame([[1,2],[3,4],[8,9]])    
B = pd.DataFrame([[7,8],[4,0]])    
C = pd.DataFrame([[9,9],[5,5]])
bb = pd.Series([0, 1, 0, 1, 2, 2, 0])

мы можем использовать

pd.concat([A, B, C]).iloc[bb.rank(method='first')-1].reset_index(drop=True)

который дает

In [269]: pd.concat([A, B, C]).iloc[bb.rank(method='first')-1].reset_index(drop=True)
Out[269]: 
   0  1
0  1  2
1  7  8
2  3  4
3  4  0
4  9  9
5  5  5
6  8  9

Это работает, потому что, когда вы используете method='first', он оценивает значения по их значениям в порядке, а затем по порядку, в котором они видны. Это означает, что мы получаем такие вещи, как

In [270]: pd.Series([1, 0, 0, 1, 0]).rank(method='first')
Out[270]: 
0    4.0
1    1.0
2    2.0
3    5.0
4    3.0
dtype: float64

который является точно (после вычитания одного) порядком iloc, в котором мы хотим выбрать строки.