Есть ли способ l oop через разные столбцы слева направо и подсчитывать, если первое число, которое он встречает в строке, равно 1? - PullRequest
1 голос
/ 08 мая 2020

Допустим, у нас есть фрейм данных

data = {'Column a':     [ 1 , 2 , 3 , 4 , 5], 
        'Column b':     [ 3 , 2 , 2 , 3 , 4], 
        'Column 1':     [ 3 , 2 , 1 , 1 , 3],
        'Column 2':     [ 4 , 2 , 1 , 2 , 2],
        'Column 3':     [ 1 , '', '', 2 , 4],
        'Column 4':     [ '', '', '', '', 1]}

df = pd.DataFrame(data=data)

Столбец a - это идентификатор, столбец b - это количество столбцов для идентификатора. Столбец 1-4 принимает некоторые значения для каждого идентификатора.

Мне нужно создать al oop, который просматривает каждый столбец от столбца 4 до столбца 1. Если первое встречное число - «1», мне нужно, чтобы оно увеличивалось на единицу.

coa cob co1 co2 co3 co4
 1   3   3   4   1
 2   2   2   2
 3   2   1   1
 4   3   1   2   2
 5   4   3   2   4   1
  • Итак, для первой строки он будет считать 1, потому что последний столбец для этой строки имеет 1.
  • Для второй строки он не будет подсчитывать , поскольку нет 1.
  • Для третьей строки будет засчитана только одна 1, потому что учитывается только первая 1 (слева).
  • Для четвертой строки , он ничего не будет считать, потому что 1 не находится в последней строке.
  • Для последней строки будет засчитано 1, потому что в
    последней строке стоит 1.

Итак, в целом я хочу, чтобы это вернуло 3.

Моя проблема связана с функцией цикла и с тем, как меняются столбцы для каждой строки, я знаю, как это сделать, только если все значения были в столбце 4.

Ответы [ 3 ]

2 голосов
/ 08 мая 2020

Попробуйте where, ffill и sum. Используйте iloc с -1, чтобы динамически выбирать последний столбец, не зная его имени.

out = df.where(df.ne('')).ffill(1).iloc[:,-1].eq(1).sum()

In [30]: out
Out[30]: 3

Чтобы конкретно применить к 4 столбцам, просто добавьте дополнительную нарезку перед where и нарезку column 4 вместо iloc

cols = ['Column 1', 'Column 2', 'Column 3', 'Column 4'] 

In [39]: df[cols].where(df.ne('')).ffill(1)['Column 4'].eq(1).sum()
Out[39]: 3
2 голосов
/ 08 мая 2020

вы можете использовать replace и ffill, например:

df['eq1'] = df.iloc[:,-4:].replace('', np.nan)\
              .ffill(axis=1).iloc[:, -1]\
              .eq(1).cumsum()
print (df)
   Column a  Column b  Column 1  Column 2 Column 3 Column 4  eq1
0         1         3         3         4        1             1
1         2         2         2         2                      1
2         3         2         1         1                      2
3         4         3         1         2        2             2
4         5         4         3         2        4        1    3
2 голосов
/ 08 мая 2020

Укажите список столбцов в обратном порядке и используйте idxmax, чтобы найти первое не пропущенное значение в каждой строке из 4–1. Мы будем использовать where, чтобы удалить строки с полностью пропущенными значениями, поскольку они портят .idxmax.

Используйте lookup, чтобы получить значения для каждой строки, а затем посмотрите, сколько из них равно 1.

cols = [f'Column {i}' for i in range(1,5)]

s = df.loc[:, cols[::-1]].ne('')
s = s.idxmax(1).where(s.notnull().all(1)).dropna()

(df.lookup(s.index, s) == 1).sum()
#3
...