#python #pandas
Вопрос:
У меня есть следующая таблица логических значений:
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'))
Указатель | val1 | val2 | val3 | val4 | val5 | val6 |
---|---|---|---|---|---|---|
1 | Правда | Ложный | Правда | Правда | Правда | Ложный |
2 | Ложный | Правда | Правда | Ложный | Правда | Ложный |
3 | Ложный | Ложный | Ложный | Правда | Ложный | Правда |
4 | Правда | Правда | Правда | Ложный | Ложный | Правда |
Я хочу создать новый фрейм данных с теми же индексами, но в каждой строке есть первые три истинных имени столбцов из предыдущего столбца.
Указатель | Истинный1 | Истинный2 | Истинный3 |
---|---|---|---|
1 | val1 | val3 | val4 |
2 | val2 | val3 | val5 |
3 | val4 | val6 | NaN |
4 | val1 | val2 | val3 |
Если строка содержит менее трех истинных значений, новый фрейм данных будет иметь нулевые значения.
Ответ №1:
Попробуй с dot
, тогда split
#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
Ответ №2:
Вы можете сделать это с 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