Условное сравнение столбцов разных датафреймов в python - PullRequest
0 голосов
/ 30 сентября 2019

У меня есть два кадра данных, каждый из которых имеет одинаковые столбцы 1) ответ участника 2) время ответа в секундах и миллисекундах (с.мс). Например,

subjectData = 

Key     RT
0   v   2.20
1   v   4.34
2   v   5.51
3   v  10.39
4   w  12.50
5   v  14.62
6   v  20.22

У меня также есть фрейм данных, который представляет собой «правильные» ответы и время. Например,

correctData = 

Key     RT
0   v   2.25
1   w   4.34
2   v   5.61
3   v  20.30

Я хочу указать, что есть совпадение как ключа ответа, так и времени ответа в течение - + 1 секунды. Итак, сначала убедитесь, что ключ ответа совпадает, и если это так, то сравните время, когда этот ответ произошел. Если это произошло в течение 1 с, оно считается правильным. Обратите внимание, что субъект мог ответить больше раз, чем было правильно. Поэтому я хочу сравнить эти столбцы независимо от порядка. Например, обратите внимание выше, что 6-й ответ в кадре subjectData совпадает с 3-м в кадре правильных данных (в течение одной секунды). Из-за этого третья запись в выходных данных - ИСТИНА, указывающая, что третий правильный ответ был найден.

Таким образом, конечный результат должен выглядеть следующим образом:

TRUE
FALSE
TRUE
TRUE

Обратите внимание, что длина вывода равна длине кадра данных correctData и указывает, какие правильные ответы соответствуют subjectData. Таким образом, это указывает на то, что субъект получил это правильно, ЕСЛИ они нажали правильную кнопку, в течение одной секунды от «правильного» времени, указанного в предоставленном кадре данных. Обратите внимание, что эти кадры данных, скорее всего, НЕ будут иметь одинаковую длину (субъект может ответить больше или меньше, чем «правильное» количество ответов). Так что «присоединиться» может не сработать здесь.

Есть идеи, как сделать это наиболее эффективно?

Ответы [ 4 ]

2 голосов
/ 30 сентября 2019
subjectData = pd.DataFrame({'Key': ['v', 'v', 'v', 'v', 'w', 'v', 'v'],
                            'RT': [2.20, 4.34, 5.51, 10.39, 12.50, 14.62, 20.22]})

correctData = pd.DataFrame({'Key': ['v', 'w', 'v', 'v'],
                            'RT': [2.25, 4.34, 5.61, 20.30]})

df = subjectData.merge(correctData.reset_index(), on='Key', how='right', 
                       suffixes=['_subj', '_corr'])

df_timed = df[(df['RT_subj'] - df['RT_corr']).between(-1,1)]

correctData.index.isin(df_timed['index'])

Выход:

array([ True, False,  True,  True])
1 голос
/ 01 октября 2019

Я бы использовал numpy.isclose

(subjectData.Key == correctData.Key) & np.isclose(subjectData.RT, correctData.RT, atol=1)

0     True
1    False
2     True
3    False
Name: Key, dtype: bool
1 голос
/ 30 сентября 2019

1) Используйте DataFrame.eq , чтобы сравнить столбец key обоих фреймов данных:

cond1=subjectData['Key'].eq(correctData['Key'])

2) затемпроверьте, находится ли он в диапазоне + -1s

cond2=(subjectData['RT']<(correctData['RT']+1))&(subjectData['RT']>(correctData['RT']-1))

3) , наконец, проверьте, какие строки удовлетворяют обоим условиям (con1,cond2):

cond1&cond2

0     True
1    False
2     True
3    False
dtype: bool
0 голосов
/ 30 сентября 2019

Посмотрите, работает ли это.

cutoff_at_index = min(correctData.shape[0], subjectData.shape[0])
equal = subjectData.Key[:cutoff_at_index] == correctData.Key[:cutoff_at_index]
between = (subjectData.RT[:cutoff_at_index] >= correctData.RT[:cutoff_at_index]-1) \
          & (subjectData.RT[:cutoff_at_index] <=correctData.RT[:cutoff_at_index]+1)
equal & between
...