Сравнение векторизации в пандах - PullRequest
1 голос
/ 22 мая 2019

На более раннюю версию вопроса ответили здесь:

Как векторизовать сравнение в кадре данных панд?

Теперь я добавил новое условие с Machine:

+---------+-----+-------+---------+
| Machine | nr  |  Time |   Event |
+---------+-----+-------+---------+
| a       |  70 |     8 |    1    |
| a       |  70 |     0 |    1    |
| b       |  70 |     0 |    1    |
| c       |  74 |    52 |    1    |
| c       |  74 |    12 |    2    |
| c       |  74 |     0 |    2    |
+---------+-----+-------+---------+

Я хочу назначить события последнему столбцу. Первая запись каждого Machine по умолчанию равна 1. То есть, если это новый Machine, Event перезапускается с 1.

If Time[i] < 7 and nr[i] != nr[i-1], then Event[i]=Event[i-1]+1. 

If Time[i] < 7 and nr[i] = nr[i-1], then Event[i]=Event[i-1]

If Time[i] > 7 then Event[i]=Event[i-1]+1. 

Как мне эффективно векторизовать это? Я хочу избежать петель. Я пытаюсь дополнить существующее решение

m = df.Machine.ne(df.Machine.shift()) 
o = np.select([t & n, t & ~n, m], [1, 0, 1], 1) 

Но это не сбрасывает Event для нового Machine на 1, я понял, только увеличивает его. Любые указатели о том, как включить это?

Ответы [ 3 ]

1 голос
/ 22 мая 2019

Разработка из вашего предыдущего решения. Это выглядит правильно на вашем образце:

t = df.Time.lt(7)
n = df.nr.ne(df.nr.shift())
m = df.Machine.ne(df.Machine.shift()) 

df['Event'] = np.select([m | t & n, t & ~n], [1, 0], 1)
df['Event'] = df.groupby('Machine').Event.cumsum()

Out[279]:
  Machine  nr  Time  Event
0       a  70     8      1
1       a  70     0      1
2       b  70     0      1
3       c  74    52      1
4       c  74    12      2
5       c  74     0      2
0 голосов
/ 22 мая 2019

В свете вашего предыдущего вопроса (и его отличного ответа) вы можете выполнить groupby('machine') и применить функцию, как если бы у вас был только один фрейм данных.

def get_event(x):
    t = x.Time.lt(7)
    n = x.nr.ne(x.nr.shift())

    o = np.select([t & n, t & ~n], [1, 0], 1)
    o[0] = 1                               # You say first value is 1
    return pd.Series(o.cumsum(), index=x.index)


df['Event'] = df.groupby('Machine', group_keys=False).apply(get_event)
0 голосов
/ 22 мая 2019

Следующее должно выдать искомый результат:

# Given you have a dataframe as df
# Create a series for grouping and looking for consecutive runs
mach_nr = df["Machine"] + df["nr"].astype("str")
mach_nr_runs = mach_nr.eq(mach_nr.shift())
# Groupby consecutive runs of each 'Machine'/'nr' combination by its
# that combination value, and take the cumulative sum of the equality
# of shifted combinations
df["Event"] = (
    mach_nr_runs.groupby(mach_nr)
                .cumsum()
                .astype("int")
                .add(1)
)
# Correct the rows where there were consecutive runs, and where 'Time' < 7
lt_7_runs = (df["Time"] < 7) & mach_nr_runs
df["Event"] -= (
    lt_7_runs.groupby(mach_nr)
              .cumsum()
              .astype("int")
)

df теперь выглядит следующим образом:

  Machine  nr  Time  Event
0       a  70     8      1
1       a  70     0      1
2       b  70     0      1
3       c  74    52      1
4       c  74    12      2
5       c  74     0      2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...