Mover valores de fila entre columnas en función de otros valores de columna en un DataFrame de Pandas

Tengo un dataframe de pandas con una lista de nombres de organismos y sus sensibilidades a los antibióticos. Deseo consolidar todos los organismos en una columna, en el siguiente dataframe, en base a las siguientes reglas.

  1. Si ORG1 == A, no haga nada;

  2. Si ORG1! = A y ORG2 == A, mueva los valores ORG2 a la columna ORG1

  3. Si ORG1! = A y ORG3 == A, mueva los valores ORG3 a la columna ORG1

Si se cumple la condición 2, además de mover el valor ORG2 a la columna ORG1, también mueva los valores de la columna en AS20 * a AS10 *.

De manera similar, si se cumple la condición 3, además de mover el valor ORG3 a la columna ORG1, también mueva los valores de la columna en AS30 * a AS10 *.

Lo intenté yo mismo escribiendo una función basada en las reglas anteriores y tuve un éxito limitado basado en lo siguiente:

If ORG2 == A: return ORG1.map(ORG2) 

Me perdí cuando intenté mapear secuencialmente AS201 -> AS101, AS202 -> AS102, AS203 -> AS103 etc. según la condición.

El otro problema que tengo es que los nombres de los organismos no son letras individuales, ni son bonitas. Una en el ejemplo es equivalente a re.match('aureus') en mi conjunto de datos.

Además, hay 20 columnas AS para cada columna ORG y más de 150,000 registros, así que espero poder generalizarlos para cualquier número de resultados de sensibilidad a los antibióticos.

Estoy luchando un poco con él, así que un par de empujones en la dirección correcta realmente ayudaría.

Gracias por adelantado.

 Índice ORG1 ORG2 ORG3 AB1 AS101 AS201 AS301 AB2 AS102 AS202 AS302
 1 A NaN NaN pluma S NaN NaN dfluc S NaN NaN
 2 ABC pluma RSS dfluc SRS
 3 BAB pen SSR dfluc SSR
 4 A NaN NaN pluma R NaN NaN dfluc S NaN NaN
 5 A NaN NaN pluma R NaN NaN dfluc S NaN NaN
 6 CAA pluma SRR dfluc RSR
 7 B NaN A pluma R NaN S dfluc S NaN S
 8 ABA pen RRR dfluc RRR
 9 A NaN NaN pluma R NaN NaN dfluc S NaN NaN

Podríamos seleccionar filas donde ORG1 != A y ORG2 == A con

 mask = (df['ORG1'] != 'A')&(df[orgi] == 'A') 

mask es entonces una serie booleana. Para copiar valores de ORG2 a ORG1, podríamos usar

 df['ORG1'][mask] = df['ORG2'][mask] 

o, como sabemos que el valor de la derecha es A , podríamos usar

 df['ORG1'][mask] = 'A' 

Copiar las columnas AS se puede hacer de manera similar.


Podemos encontrar filas cuyo valor de columna contenga una cadena como 'aureus' con

 df[orgi].str.contains('aureus') == True 

str.contains puede tomar cualquier patrón de str.contains regulares como su argumento. Consulte los documentos: Métodos de cadena vectorizados .

Nota: por lo general, sería suficiente usar df[orgi].str.contains('aureus') (sin el == True , pero dado que df[orgi] puede contener valores de NaN , también debemos asignar los NaN a Falso , entonces usamos df[orgi].str.contains('aureus') == True .


 import pandas as pd filename = 'data.txt' df = pd.read_table(filename, delimiter='\s+') print(df) # Index ORG1 ORG2 ORG3 AB1 AS101 AS201 AS301 AB2 AS102 AS202 AS302 # 0 1 A NaN NaN pen S NaN NaN dfluc S NaN NaN # 1 2 ABC pen RSS dfluc SRS # 2 3 BAB pen SSR dfluc SSR # 3 4 A NaN NaN pen R NaN NaN dfluc S NaN NaN # 4 5 A NaN NaN pen R NaN NaN dfluc S NaN NaN # 5 6 CAA pen SRR dfluc RSR # 6 7 B NaN A pen R NaN S dfluc S NaN S # 7 8 ABA pen RRR dfluc RRR # 8 9 A NaN NaN pen R NaN NaN dfluc S NaN NaN for i in range(2,4): orgi = 'ORG{i}'.format(i=i) # mask = (df['ORG1'] != 'A')&(df[orgi] == 'A') mask = (df['ORG1'].str.contains('A') == False)&(df[orgi].str.contains('A') == True) # Move ORGi --> ORG1 df['ORG1'][mask] = df[orgi][mask] for j in range(1,4): # Move ASij --> AS1j source_as = 'AS{i}{j:02d}'.format(i=i, j=j) target_as = 'AS1{j:02d}'.format(i=i, j=j) try: df[target_as][mask] = df[source_as][mask] except KeyError: pass print(df) 

rendimientos

  Index ORG1 ORG2 ORG3 AB1 AS101 AS201 AS301 AB2 AS102 AS202 AS302 0 1 A NaN NaN pen S NaN NaN dfluc S NaN NaN 1 2 ABC pen RSS dfluc SRS 2 3 AAB pen SSR dfluc SSR 3 4 A NaN NaN pen R NaN NaN dfluc S NaN NaN 4 5 A NaN NaN pen R NaN NaN dfluc S NaN NaN 5 6 AAA pen RRR dfluc SSR 6 7 A NaN A pen S NaN S dfluc S NaN S 7 8 ABA pen RRR dfluc RRR 8 9 A NaN NaN pen R NaN NaN dfluc S NaN NaN 

Tenga en cuenta que si ORG2 == A y ORG3 == A , los valores en la columna AS20* y AS30* compiten para sobrescribir los valores en la columna AS10* . No estoy seguro de qué valor quieres ganar. En el código anterior, gana la última columna, que sería AS30* .