Панды устанавливают каждый второй дубликат значения строки в ноль - PullRequest
1 голос
/ 24 сентября 2019

У меня есть Dataframe с 15K строк.Если в столбце 'val1' повторяются 3, я хочу установить каждую секунду на ноль.Если «val1» не повторяется, то стоит остаться 3. Я могу добиться этого с помощью итерации по фрейму данных, но это медленно

У меня есть что-то вроде этого:

import pandas as pd


dates = pd.date_range('2008-10-01', periods=15, freq='D')
df = pd.DataFrame({'val1': (0,0,3,3,3,3,3,0,0,3,0,3,3,3,0) },index=dates) 
print(df)
            val1
2008-10-01     0
2008-10-02     0
2008-10-03     3
2008-10-04     3
2008-10-05     3
2008-10-06     3
2008-10-07     3
2008-10-08     0
2008-10-09     0
2008-10-10     3
2008-10-11     0
2008-10-12     3
2008-10-13     3
2008-10-14     3
2008-10-15     0

What I want to archive is this:

df = pd.DataFrame({ 'val1': (0,0,3,3,3,3,3,0,0,3,0,3,3,3,0),'val2': (0,0,3,0,3,0,3,0,0,3,0,3,0,3,0)},index=dates ) 
print(df)

 val1  val2
2008-10-01     0     0
2008-10-02     0     0
2008-10-03     3     3
2008-10-04     3     0
2008-10-05     3     3
2008-10-06     3     0
2008-10-07     3     3
2008-10-08     0     0
2008-10-09     0     0
2008-10-10     3     3
2008-10-11     0     0
2008-10-12     3     3
2008-10-13     3     0
2008-10-14     3     3
2008-10-15     0     0

Единственное работающее решениеЯ нашел, чтобы перебирать строки, что ужасно медленно ..:

df['val3']=0
for i in range(0,len(df.index)):

    if (df['val1'][i]==3) & (df['val1'][i-1]==3) & (df['val2'][i-2]!=3):
            df['val3'][i-1]=3

    if (df['val1'][i]==0) & (df['val1'][i-1]==3):
            df['val3'][i-1]=3


val1  val2  val3
2008-10-01     0     0     0
2008-10-02     0     0     0
2008-10-03     3     3     3
2008-10-04     3     0     0
2008-10-05     3     3     3
2008-10-06     3     0     0
2008-10-07     3     3     3
2008-10-08     0     0     0
2008-10-09     0     0     0
2008-10-10     3     3     3
2008-10-11     0     0     0
2008-10-12     3     3     3
2008-10-13     3     0     0
2008-10-14     3     3     3
2008-10-15     0     0     0

Any suggestions to achieve this without iteration or to make iterartion faster?

Ответы [ 2 ]

1 голос
/ 24 сентября 2019

Использование:

dates = pd.date_range('2008-10-01', periods=15, freq='D')
df = pd.DataFrame({'val1': (0,0,3,3,3,3,3,0,0,3,0,3,3,3,0) },index=dates) 

#create consecutive groups
g = df['val1'].ne(df['val1'].shift()).cumsum()

#create counter per groups with modulo 2 and compare by 0
m = df.groupby(g).cumcount() % 2 == 0
#alternative, thanks @Erfan
#m = df.groupby(g).cumcount().mod(2).eq(0)

#set new column
df['val2'] = df['val1'].where(m, 0)
            val1  val2
2008-10-01     0     0
2008-10-02     0     0
2008-10-03     3     3
2008-10-04     3     0
2008-10-05     3     3
2008-10-06     3     0
2008-10-07     3     3
2008-10-08     0     0
2008-10-09     0     0
2008-10-10     3     3
2008-10-11     0     0
2008-10-12     3     3
2008-10-13     3     0
2008-10-14     3     3
2008-10-15     0     0
1 голос
/ 24 сентября 2019

Сначала мы создаем индикатор, который присваивает каждой группе одинаковые значения, в данном случае все значения 3.Затем сгруппируйте их и получите каждый 2nd индекс этих групп с range(step=2).Наконец, мы определяем эти индексы с помощью .loc и присваиваем 0:

grps = df['val1'].diff().ne(0).cumsum()

idx = df.groupby(grps).apply(lambda x: x.iloc[[x for x in range(1, len(x), 2)]]).index.get_level_values(1)

df.loc[idx, 'val1'] = 0

Выход

            val1
2008-10-01     0
2008-10-02     0
2008-10-03     3
2008-10-04     0
2008-10-05     3
2008-10-06     0
2008-10-07     3
2008-10-08     0
2008-10-09     0
2008-10-10     3
2008-10-11     0
2008-10-12     3
2008-10-13     0
2008-10-14     3
2008-10-15     0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...