Сравнение предыдущих значений строк в Pandas DataFrame
import pandas as pd
data={'col1':[1,3,3,1,2,3,2,2]}
df=pd.DataFrame(data,columns=['col1'])
print df
col1
0 1
1 3
2 3
3 1
4 2
5 3
6 2
7 2
У меня есть следующий Pandas DataFrame, и я хочу создать еще один столбец, который сравнивает предыдущую строку col1, чтобы узнать, равны ли они. Какой был бы лучший способ сделать это? Это будет похоже на следующий DataFrame. благодаря
col1 match
0 1 False
1 3 False
2 3 True
3 1 False
4 2 False
5 3 False
6 2 False
7 2 True
Ответы
Ответ 1
Вам нужно eq
со shift
:
df['match'] = df.col1.eq(df.col1.shift())
print (df)
col1 match
0 1 False
1 3 False
2 3 True
3 1 False
4 2 False
5 3 False
6 2 False
7 2 True
Или вместо eq
используйте ==
, но он немного медленнее в большом DataFrame:
df['match'] = df.col1 == df.col1.shift()
print (df)
col1 match
0 1 False
1 3 False
2 3 True
3 1 False
4 2 False
5 3 False
6 2 False
7 2 True
Сроки:
import pandas as pd
data={'col1':[1,3,3,1,2,3,2,2]}
df=pd.DataFrame(data,columns=['col1'])
print (df)
#[80000 rows x 1 columns]
df = pd.concat([df]*10000).reset_index(drop=True)
df['match'] = df.col1 == df.col1.shift()
df['match1'] = df.col1.eq(df.col1.shift())
print (df)
In [208]: %timeit df.col1.eq(df.col1.shift())
The slowest run took 4.83 times longer than the fastest. This could mean that an intermediate result is being cached.
1000 loops, best of 3: 933 µs per loop
In [209]: %timeit df.col1 == df.col1.shift()
1000 loops, best of 3: 1 ms per loop
Ответ 2
1) подход pandas: Используйте diff
:
df['match'] = df['col1'].diff().eq(0)
2) метод numpy: используйте np.ediff1d
.
df['match'] = np.ediff1d(df['col1'].values, to_begin=np.NaN) == 0
Оба продукта:
Сроки: (для того же DF
используемого @jezrael)
%timeit df.col1.eq(df.col1.shift())
1000 loops, best of 3: 731 µs per loop
%timeit df['col1'].diff().eq(0)
1000 loops, best of 3: 405 µs per loop
Ответ 3
Здесь Numpy массивов подход, основанный на использовании slicing
, что позволяет нам использовать мнение в входном массив в целях эффективности -
def comp_prev(a):
return np.concatenate(([False],a[1:] == a[:-1]))
df['match'] = comp_prev(df.col1.values)
Пример прогона -
In [48]: df['match'] = comp_prev(df.col1.values)
In [49]: df
Out[49]:
col1 match
0 1 False
1 3 False
2 3 True
3 1 False
4 2 False
5 3 False
6 2 False
7 2 True
Runtime test -
In [56]: data={'col1':[1,3,3,1,2,3,2,2]}
...: df0=pd.DataFrame(data,columns=['col1'])
...:
#@jezrael soln1
In [57]: df = pd.concat([df0]*10000).reset_index(drop=True)
In [58]: %timeit df['match'] = df.col1 == df.col1.shift()
1000 loops, best of 3: 1.53 ms per loop
#@jezrael soln2
In [59]: df = pd.concat([df0]*10000).reset_index(drop=True)
In [60]: %timeit df['match'] = df.col1.eq(df.col1.shift())
1000 loops, best of 3: 1.49 ms per loop
#@Nickil Maveli soln1
In [61]: df = pd.concat([df0]*10000).reset_index(drop=True)
In [64]: %timeit df['match'] = df['col1'].diff().eq(0)
1000 loops, best of 3: 1.02 ms per loop
#@Nickil Maveli soln2
In [65]: df = pd.concat([df0]*10000).reset_index(drop=True)
In [66]: %timeit df['match'] = np.ediff1d(df['col1'].values, to_begin=np.NaN) == 0
1000 loops, best of 3: 1.52 ms per loop
# Posted approach in this post
In [67]: df = pd.concat([df0]*10000).reset_index(drop=True)
In [68]: %timeit df['match'] = comp_prev(df.col1.values)
1000 loops, best of 3: 376 µs per loop
Ответ 4
Я удивлен, что никто не упомянул здесь метод прокатки. Прокрутка может быть легко использована для проверки того, что n-предыдущие значения одинаковы или для выполнения каких-либо пользовательских операций. Это, конечно, не так быстро, как использование diff или shift, но его можно легко адаптировать для больших окон:
df['match'] = df['col1'].rolling(2).apply(lambda x: len(set(x)) != len(x),raw= True).replace({0 : False, 1: True})