我有以下布尔值表:
pd.DataFrame(data={'val1': [True, False, False, True],
'val2': [False, True, False, True],
'val3': [True, True, False, True],
'val4': [True, False, True, False],
'val5': [True, True, False, False],
'val6': [False, False, True, True]},
index=pd.Series([1, 2, 3, 4], name='index'))
我想创建一个具有相同索引的新数据帧,但每行都有前一列的前三个 True 列名。
如果一行少于三个真值,则新数据帧将具有空值。
尝试使用点
,然后拆分
#df = df.set_index('index')
out = df.dot(df.columns + ',').str[:-1].str.split(',',expand=True).iloc[:,:3]
out
Out[258]:
0 1 2
index
1 val1 val3 val4
2 val2 val3 val5
3 val4 val6 None
4 val1 val2 val3
您可以使用numpy
argsort
来执行此操作,以根据True
值的位置对列进行切片。
然后使用where
来NaN
是False
的行,以防True
值太少。
import numpy as np
import pandas as pd
# Get the first `N` True columns.
N = 3
arr = df.to_numpy()
data = df.columns.to_numpy()[(~arr).argsort(axis=1, kind='stable')[:, :N]]
mask = np.ones_like(data).cumsum(1) <= arr.sum(1)[:, None]
res = pd.DataFrame(data, columns=[f'TrueVal{i+1}' for i in range(N)],
index=df.index).where(mask)
print(res)
TrueVal1 TrueVal2 TrueVal3
index
1 val1 val3 val4
2 val2 val3 val5
3 val4 val6 NaN
4 val1 val2 val3