Подсчет записей в строках для настройки другого столбца, панды

1

Я пытаюсь обновить записи в столбцах, подсчитывая частоту записей в разных столбцах. Вот образец моих данных. Фактические данные состоят из 10 тыс. Выборок, каждая из которых имеет длину 220 (220 секунд).

d = {'ID':['a12', 'a12','a12','a12','a12', 'a12', 'a12','a12','v55','v55','v55','v55','v55','v55','v55', 'v55'], 
     'Exp_A':[0.012,0.154,0.257,0.665,1.072,1.514,1.871,2.144, 0.467, 0.812,1.59,2.151,2.68,3.013,3.514,4.015], 
     'freq':['00:00:00', '00:00:01', '00:00:02', '00:00:03', '00:00:04',
                '00:00:05', '00:00:06', '00:00:07','00:00:00', '00:00:01', '00:00:02', '00:00:03', '00:00:04',
                '00:00:05', '00:00:06', '00:00:07'],
     'A_Bullseye':[0,0,0,0,1,0,1,0, 0,0,1,0,0,0,1,0], 'A_Bull_Total':[0,0,0,0,0,1,1,2,0,0,0,1,1,1,1,2], 'A_Shot':[0,1,1,1,0,1,0,0, 1,1,0,1,0,1,0,0]}
df = pd.DataFrame(data=d)

За каждую секунду может быть зарегистрирован только Bullseye или Shot.

Count1: число df.A_Shot == 1 перед первым df.A_Bullseye == 1 для каждого ID равно 3 & 2 for ID=a12 and ID=v55 resp.

Count2: количество df.A_Shot == 1 от конца count1 до второго df.A_Bullseye == 1, 1 для df[df.ID=='a12'] и 2 for df[df.ID=='v55']

Где i в count(i): df.groupby(by='ID')[A_Bull_Total].max(). Здесь i 2.

Итак, если я смогу вычислить среднее количество для каждого i, тогда я смогу скорректировать значения df.Exp_A, используя среднее из вышеупомянутых значений.

mask_A_Shot= df.A_Shot == 1
mask_A_Bullseye= df.A_Bulleseye == 0
mask = mask_A_Shot  & mask_A_Bulleseye 
df[mask.groupby(df['ID'])].mean()

В идеале я хотел бы иметь что-то подобное для каждого я (яблочко), сколько выстрелов необходимо и сколько секунд это заняло.

Теги:
pandas
mean

1 ответ

3

Создайте ключ группировки Bullseye внутри каждого идентификатора, используя .cumsum и затем вы сможете узнать, сколько выстрелов и сколько времени прошло между яблочками.

import pandas as pd

df['freq'] = pd.to_timedelta(df.freq, unit='s')
df['Bullseye'] = df.groupby('ID').A_Bullseye.cumsum()+1

# Chop off any shots after the final bullseye
m = df.Bullseye <= df.groupby('ID').A_Bullseye.transform(lambda x: x.cumsum().max())

df[m].groupby(['ID', 'Bullseye']).agg({'A_Shot': 'sum', 
                                       'freq': lambda x: x.max()-x.min()})

Выход:

              A_Shot     freq
ID  Bullseye                 
a12 1              3 00:00:03
    2              1 00:00:01
v55 1              2 00:00:01
    2              2 00:00:03

Редактировать:

Учитывая ваш комментарий, вот как я буду действовать. Мы собираемся .shift столбец " .shift поэтому вместо увеличения счетчика в яблочко мы увеличиваем счетчик на строку после яблочка. Мы A_Shot так что A_Shot также считаются выстрелом.

df['freq'] = pd.to_timedelta(df.freq, unit='s')
df['Bullseye'] = df.groupby('ID').A_Bullseye.apply(lambda x: x.shift().cumsum().fillna(0)+1)

# Also consider Bullseye as a shot:
df.loc[df.A_Bullseye == 1, 'A_Shot'] = 1

# Chop off any shots after the final bullseye
m = df.Bullseye <= df.groupby('ID').A_Bullseye.transform(lambda x: x.cumsum().max())

df1 = (df[m].groupby(['ID', 'Bullseye'])
            .agg({'A_Shot': 'sum', 
                  'freq': lambda x: (x.max()-x.min()).total_seconds()}))

Выход: df1

              A_Shot  freq
ID  Bullseye              
a12 1.0            4   4.0
    2.0            2   1.0
v55 1.0            3   2.0
    2.0            3   3.0

И теперь, поскольку freq - целое число секунд, вы можете легко делить:

df1.A_Shot / df1.freq

#ID   Bullseye
#a12  1.0         1.0
#     2.0         2.0
#v55  1.0         1.5
#     2.0         1.0
#dtype: float64
  • 1
    Спасибо за элегантное решение! Но учитывая размер фактических данных (более 10 тыс. Уникальных идентификаторов), можно ли, скажем, подсчитать, сколько всего выстрелов / времени требуется для каждого яблочка? Так у меня будет средняя цифра для каждого яблочка?
  • 0
    @AZ Я, конечно, могу помочь с этим. Единственный вопрос, который у меня возникает, это когда 'A_bullseye' равен 1, это отдельный выстрел, который был зарегистрирован как яблочко, или это просто предыдущий выстрел, зарегистрированный как яблочко в следующую секунду? Например, a12 имеет 3 выстрела за 3 секунды (третий - яблочко) или 3 выстрела, которые не являются яблоком, а затем 4-й выстрел в 00:00:04 - яблочко?
Показать ещё 4 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню