Tengo un marco de datos:

df = pd.DataFrame({'p1_c': [1,10,3,40],
                   'p2_c': [4,3,4,14],
                   'p3_c': [5,2,8,78],
                   'p1_v': [776,1776,300,600],
                   'p2_v': [998,98,100,100],
                   'p3_v': [800,80,50,500]
                  })
df
   p1_c  p2_c  p3_c  p1_v  p2_v  p3_v
0     1     4     5   776   998   800
1    10     3     2  1776    98    80
2     3     4     8   300   100    50
3    40    14    78   600   100   500

(p1_c, p1_v), (p2_c, p2_v), (p3_c, p3_v) están en grupos y describen lo mismo.
Quiero obtener el valor de columna v-th del que tiene el valor c-th más alto

Por ejemplo, ver en la fila 0:

df[[p1_c,p2_c,p3_c]].max(axis=1)   
#get the max value i.e p3_c

Entonces, quiero el valor p3_v como salida (es decir, 800). Mismo patrón seguido de la fila 1,2 y 3.

SALIDA ESPERADA

   p1_c  p2_c  p3_c  p1_v   p2_v  p3_v  RESULT
 0  1     4     5    776    998    800   800
 1  10    3     2    1776    98    80    1776
 2  3     4     8    300    100    50    50
 3  40   154    78   600    100    500   100
3
Amit 25 jun. 2020 a las 17:08

5 respuestas

La mejor respuesta

Puede intentar esto con df.to_records, que me parece más simple, y podría ser la forma más rápida:

df['RESULT']=[row[list(row).index(max(list(row)[1:4]))+3]for row in df.to_records()]
print(df)

Salida:

   p1_c  p2_c  p3_c  p1_v  p2_v  p3_v  RESULT
0     1     4     5   776   998   800     800
1    10     3     2  1776    98    80    1776
2     3     4     8   300   100    50      50
3    40    14    78   600   100   500     500
1
MrNobody33 25 jun. 2020 a las 19:54

Puede hacerlo con filter para obtener columnas _c y _v y usar where para reemplazar por valores nan en columnas _v donde el valor en la columna _c no es la máscara por fila. luego obtén el max

#get only _c columns
dfc = df.filter(regex='_c')

df['RESULT'] = (df.filter(regex='_v') #get _p columns
                  #keep value in _p where max in _c per row 
                  .where(dfc.eq(dfc.max(axis=1).to_numpy()[:, None]).to_numpy())
                  .max(axis=1) #get the max
               )
print (df)
   p1_c  p2_c  p3_c  p1_v  p2_v  p3_v  RESULT
0     1     4     5   776   998   800   800.0
1    10     3     2  1776    98    80  1776.0
2     3     4     8   300   100    50    50.0
3    40   154    78   600   100   500   100.0
0
Ben.T 25 jun. 2020 a las 14:30

Definitivamente no es una solución ideal pero resuelve el problema.

from pandas import DataFrame

df = DataFrame({'p1_c': [1,10,3,40], 'p2_c': [4,3,4,14], 'p3_c': [5,2,8,78], 'p1_v': [776, 1776, 300, 600], 'p2_v': [998, 98, 100, 100], 'p3_v': [800, 80, 50, 500]})

df['RESULT'] = [df.loc[i, df.loc[i, df.columns[:3]].idxmax(axis=1)[:-1] + 'v'] for i in range(len(df))]
   p1_c  p2_c  p3_c  p1_v  p2_v  p3_v  RESULT
0     1     4     5   776   998   800     800
1    10     3     2  1776    98    80    1776
2     3     4     8   300   100    50      50
3    40    14    78   600   100   500     500
0
Berkay Öztürk 25 jun. 2020 a las 14:32

Prueba esto

data={'p1_c':[1,10,3,40],'p2_c':[4,3,3,14],'p3_c':[5,2,8,78],'p1_v':[776,1776,300,600],'p2_v':[998,98,100,100],'p3_v':[800,80,50,500]}
df_1=pd.DataFrame(data)
list=[]
for i in range(4):
  if df_1[['p1_c','p2_c','p3_c']].max(axis=1)[i]==df_1.loc[i,'p3_c']:
     list.append(df_1.loc[i,'p3_v'])
  else:
     list.append(df_1[['p1_v','p2_v']].max(axis=1)[i])


df_1['Result']=list
df_1

Salida

  p1_c  p2_c    p3_c    p1_v    p2_v    p3_v    Result
0         1     4   5   776     998       800     800
1         10    3   2   1776    98        80      1776
2          3    3   8   300     100       50      50
3         40    14  78  600     100       500     500
0
NAGA RAJ S 25 jun. 2020 a las 14:37

Use, Series.str.endswith junto con DataFrame.idxmax junto con axis=1 para extraer los nombres de columna que terminan con _c y que contienen los valores máximos, luego use Series.str.rstrip junto con .add para reemplazar el _c con {{ X7}} en esos nombres de columna, finalmente use DataFrame.lookup para obtener los valores del marco de datos basado en esto cols:

cols = df.loc[:, df.columns.str.endswith('_c')].idxmax(axis=1)
cols = cols.str.rstrip('_c').add('_v')
df['RESULT'] = df.lookup(df.index, cols)

Resultado:

# print(df)

   p1_c  p2_c  p3_c  p1_v  p2_v  p3_v  RESULT
0     1     4     5   776   998   800     800
1    10     3     2  1776    98    80    1776
2     3     4     8   300   100    50      50
3    40   154    78   600   100   500     100
0
Shubham Sharma 25 jun. 2020 a las 14:38