Manera más rápida de cambiar cada valor en dataframe de ACUERDO al valor original

Tengo un dataframe con 30000 columnas y 4000 filas. Cada entrada de la celda contiene un número entero. Para CADA entrada, quiero multiplicar el contenido original con log(k/m),

donde k es el número total de filas de la ie.4000 y m es el número total de cero filas de ESA COLUMNA en PARTICULAR.

Mi actual código de usos:

for column in df.columns:
    m = len(df[column].to_numpy().nonzero())
    df[column] = df[column].apply(lambda x: x * np.log10(4000/m))

Esto me lleva horas (????). Espero que haya alguna manera más rápida de hacerlo, alguien tiene alguna idea?

Gracias

1 Respuestas

  • Dennis Hansen
    4 de mayo de 2019

    Primera generar datos de ejemplo:

    np.random.seed(123)
    
    df = pd.DataFrame(np.random.rand(4, 5)*500).astype(int).replace(range(100, 200), 0)
    
    Result:
    
        0   1   2   3   4
    0   348 0   0   275 359
    1   211 490 342 240 0
    2   0   364 219 29  0
    3   368 91  87  265 265
    
    

    Lo siguiente que definir un vector con la que contiene el cero de la columna de cuenta:

    non_zeros = df.ne(0).sum().values
    
    # Giving me: array([3, 3, 3, 4, 2], dtype=int64)
    

    Desde allí puedo encontrar el registro-factor para cada columna:

    faktor = np.mat(np.log10(len(df)/ non_zeros))
    
    # giving me: matrix([[0.12493874, 0.12493874, 0.12493874, 0.        , 0.30103   ]])
    
    

    Luego multiplicando cada columna con su factor de conversión y vuelta a DataFrame:

    res = np.multiply(np.mat(df), faktor)
    df = pd.DataFrame(res)