Tengo dos marcos de datos, cada uno tiene las mismas columnas 1) la respuesta hecha por un participante 2) el tiempo de respuesta en segundos y milisegundos (s.ms). Por ejemplo,

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

También tengo un marco de datos que son las respuestas y tiempos 'correctos'. Por ejemplo,

correctData = 

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

Quiero indicar que hay una coincidencia tanto en la clave de respuesta Y el tiempo de respuesta dentro de - + 1 segundo. Por lo tanto, primero verifique que la clave de respuesta coincida, y si es así, compare la hora en que ocurrió esta respuesta. Si ocurrió dentro de 1s, se considera correcto. Tenga en cuenta que el sujeto puede haber respondido más veces de lo correcto. Entonces quiero comparar estas columnas sin importar el orden. Por ejemplo, observe que la sexta respuesta en el cuadro subjectData coincide con la tercera en el cuadro correctoData (dentro de un segundo). Debido a esto, la tercera entrada en la salida es VERDADERA, lo que indica que la tercera respuesta correcta coincidió.

Entonces el resultado final debería verse así

TRUE
FALSE
TRUE
TRUE

Observe que la salida tiene la misma longitud que el marco de datos correctData e indica qué respuestas correctas coinciden con el subjectData. Por lo tanto, indica que el sujeto lo entendió correctamente SI presionaron el botón correcto, dentro de un segundo del tiempo 'correcto' que figura en el marco de datos proporcionado. Tenga en cuenta que estos marcos de datos probablemente NO tendrán la misma longitud (el sujeto puede responder más o menos que el número 'correcto' de respuestas). Entonces 'unirse' puede no funcionar aquí.

¿Alguna idea sobre cómo hacer esto de manera más eficiente?

0
Katie 30 sep. 2019 a las 23:03

4 respuestas

La mejor respuesta
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'])

Salida:

array([ True, False,  True,  True])
2
EliadL 1 oct. 2019 a las 21:40

Yo usaría 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
piRSquared 30 sep. 2019 a las 21:42

1) Use DataFrame.eq para comparar la columna key de ambos marcos de datos:

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

2) luego verifique si está en el rango de + -1s

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

3) finalmente verifique qué filas cumplen ambas condiciones (con1,cond2):

cond1&cond2

0     True
1    False
2     True
3    False
dtype: bool
1
ansev 30 sep. 2019 a las 20:37

A ver si esto funciona.

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
0
DarkDrassher34 1 oct. 2019 a las 21:32
58174590