Páginas

domingo, 29 de junio de 2014

Python: Un programa escrito de atrás para adelante.

No se como sera el proceso mental de los programadores, pero en mi caso cuando necesito hacer algún script comienzo decidiendo la acción clave que va a realizar el programa y escribo eso primero.   Las variables y como cargarles un valor es algo que voy decidiendo a medida que lo voy necesitando.

Por ejemplo hoy en una clase nos pidieron un mini programa para encontrar el numero mayor entre un listado ingresado por el usuario.  Lo primero que hice fue plantear que si el numero actual (number) es mayor al numero máximo (maxnumber) entonces el numero actual se convertirá en el nuevo numero máximo:


if number > maxnumber:      
    maxnumber = number

Bien ahora, de donde saco el valor de number? Pues de un listado de datos que debe ingresar el usuario. Para eso se utiliza la función de raw_input() y los números que se ingresen se almacenan en una variable:

numberlist = raw_input("Enter your list of numbers, separated by commas >")

Pero number list va a contener una cadena de texto, como puedo sacar cada numero de esa cadena? con la función str.split()

numberarray = numberlist.split(",")

Lo que hice fue separar por comas todos los datos ingresados en la cadena de texto numberlist y guardarlos en la variable numberarray. Esto es lo que tengo hasta ahora:

numberlist = raw_input("Enter your list of numbers, separated by commas >")
numberarray = numberlist.split(',')

if number > maxnumber:
        maxnumber = number

Entonces ya tengo una colección de números, ahora me toca que comparar cada numero dentro de esa lista con el numero máximo. Pero de donde saco el maxnumber inicial? bueno pues de la colección de números en numberarray, extraigo el primer numero, que se encuentra en la posición 0:

maxnumber = numberarray[0]

Pero esperen un momento, todos los datos en numberarray están en formato de texto. Entonces lo que extraiga de esa lista debo convertirlo a formato de numero integral con la función int():

maxnumber = int(numberarray[0])

Entonces ahi si,  hasta ahora llevo:

numberlist = raw_input("Enter your list of numbers, separated by commas >")
numberarray = numberlist.split(',')
maxnumber = int(numberarray[0])

if number > maxnumber:
        maxnumber = number

Ya tengo todos los datos que necesitaba, una colección de números para comparar y un numero máximo inicial de referencia.  Ahora viene lo bueno, como extraer el valor de "number" de la colección de números para compararlo con maxnumber y repetir ese proceso para cada uno de los números? con los maravillosos Loops.

for number in numberarray:

Con este código estoy diciendo dos cosas:

Cada elemento dentro de "numberarray" se asignará temporalmente a la variable  "number".
Que el proceso que escriba a continuación se repetirá para cada elemento dentro de numberarray.

for number in numberarray:
    number = int(number)
 
    if number > maxnumber:
        maxnumber = number

Como tomos los numeros en la colección están en formato de texto, tengo que convertir cada numero a formato integral con la función int(). Al final incluyo un print para mostrar el resultado final y listo. El código me queda de esta manera:


numberlist = raw_input("Enter your list of numbers, separated by commas >")
numberarray = numberlist.split(',')
maxnumber = int(numberarray[0])

for number in numberarray:
    number = int(number)
 
    if number > maxnumber:
        maxnumber = number


print "El numero mayor es: %s" %maxnumber

Y en la ejecuccion se ve así:


Rubens-MacBook-Pro:python eljayan$ python maxnum.py

Enter your list of numbers, separated by commas >1,4,3,5,6,6,1,2,1,21,31,22,14,54,3,2,3,44,23,43,13
El numero mayor es: 54




Python: Como separar las palabras en una cadena de texto con la función str.split()

Solo hay que especificar cual es el criterio o el separador, en este caso es una coma (",") pero puede ser también un espacio (" "), o cualquier otro simbolo.

>>> cadenaDeTexto = "5,4,3,2,1,Kabooom!"

>>> cadenaDeTexto.split(",")
['5', '4', '3', '2', '1', 'Kabooom!']

miércoles, 25 de junio de 2014

VBA Excel: Funcion que llama un procedimiento para enviar un email.


Pensé que no podia llamar sub procedures desde una funcion. Ojo que tienes que activar la libreria de objectos de Outlook. (Ir a Tools/References y seleccionar Microsoft Office Outlook Object Library)

Sub send_notice(mailsubject As String, process As String)

Dim mlook As Outlook.MailItem

Set mlook = Outlook.Application.CreateItem(olMailItem)
mySubject = mailsubject
mlook.To = "ruben.torres@huawei.com"
mlook.Subject = mailsubject
mlook.Body = "Dear Friend, the " & process & " is complete."
mlook.Send

End Sub


Function status(start As Date, finish As Date)

If start <> 0 And finish <> 0 Then
    
    Call send_notice("hello", "process finished")
    status = "Finished"
Else
    status = "Pending"
End If

End Function

sábado, 21 de junio de 2014

R Programming: Como extraer los datos de una variable.

#Puedo extraer los valores de la columna "nitrate" con los brackets
> data[ ,"nitrate"]

  [1] 0.632 0.173 0.568 0.719 0.479 0.211 0.266 0.302 1.800 0.651 0.507 0.669 0.602 0.351
 [15] 0.295 1.200 1.160 1.200 0.553 0.993 0.404 0.226 0.559 0.363 0.474 0.531 0.221 0.429
 [29] 0.537 0.460 0.409 0.204 0.355 0.191 1.030 1.400 0.671 0.815 0.236 0.902 0.233 0.189
 [43] 0.149 0.657 0.428 0.554 0.520 0.186 0.576 0.372 0.223 0.466 0.372 0.590 0.219 0.739
 [57] 0.421 0.250 0.312 1.010 1.040 0.491 0.506 0.340 0.203 0.472 0.941 0.570 0.215 0.286
 [71] 0.290 0.209 0.188 0.342 1.100 0.964 0.715 0.486 0.193 0.378 0.285 0.276 0.326 1.480
 [85] 0.518 0.118 0.227 1.770 0.205 0.322 0.177 0.503 0.193 0.267 0.743 1.830 0.425 0.803
 [99] 0.979 0.479 0.665 0.337 1.610 0.331 0.178 0.283 1.610 0.400 1.080 0.140 0.222 0.299
[113] 0.382 0.363 0.446 0.577 1.140

#Y sacar el promedio de todas las filas, y la columna "nitrate"
> mean(data[ ,"nitrate"])
[1] 0.5481368

> #Pero hay otra manera mas sencilla. Si tengo las siguientes variables:

> names(data)
[1] "Date"    "sulfate" "nitrate" "ID"     

> #Y necesito sacar la media de la variable "nitrate" puedo extraer los valores de esta variable con el signo de dollar $

> data$nitrate
  [1] 0.632 0.173 0.568 0.719 0.479 0.211 0.266 0.302 1.800 0.651 0.507 0.669 0.602 0.351
 [15] 0.295 1.200 1.160 1.200 0.553 0.993 0.404 0.226 0.559 0.363 0.474 0.531 0.221 0.429
 [29] 0.537 0.460 0.409 0.204 0.355 0.191 1.030 1.400 0.671 0.815 0.236 0.902 0.233 0.189
 [43] 0.149 0.657 0.428 0.554 0.520 0.186 0.576 0.372 0.223 0.466 0.372 0.590 0.219 0.739
 [57] 0.421 0.250 0.312 1.010 1.040 0.491 0.506 0.340 0.203 0.472 0.941 0.570 0.215 0.286
 [71] 0.290 0.209 0.188 0.342 1.100 0.964 0.715 0.486 0.193 0.378 0.285 0.276 0.326 1.480
 [85] 0.518 0.118 0.227 1.770 0.205 0.322 0.177 0.503 0.193 0.267 0.743 1.830 0.425 0.803
 [99] 0.979 0.479 0.665 0.337 1.610 0.331 0.178 0.283 1.610 0.400 1.080 0.140 0.222 0.299
[113] 0.382 0.363 0.446 0.577 1.140

> #Y con la funcion mean() saco el promedio:

> mean(data$nitrate)
[1] 0.5481368

miércoles, 18 de junio de 2014

VBA Excel: Eliminar texto no deseado delante de otro texto

Los números de pedido pueden ser "000218XXXXXXX" o "WTXXXXX" o "00PXXXX" 

Sin embargo a veces me envían "Pedido 000218XXXXXXX" o "PL No. wtXXXXX"

Como eliminar ese texto no deseado "PL No. " delante de los numeros de pedido:

Sub validation()

Dim pl As String
Dim Position As Integer
Dim i As Integer
Dim opciones(1 To 5) As String


'PROCESO PARA ELIMINAR EL TEXTO NO DESEADO DELANTE DEL NUMERO DE PEDIDO.

'las posibles opciones con las que comienzan mis numeros de pedido:

opciones(1) = "000"
opciones(2) = "005"
opciones(3) = "00Y"
opciones(4) = "00P"
opciones(5) = "WT"


ThisWorkbook.ActiveSheet.Range("d4").NumberFormat = "@" 'convierte a formato de texto
i = 1  'ser'a el contador de las opciones

For i = 1 To 5 'hacemos un loop por todas las opciones
    Do
        pl = UCase(ThisWorkbook.ActiveSheet.Range("d4").Value)  'asigna el valor de la celda a la variable
        Position = InStr(pl, opciones(i))            'busca la posicion de la opcion en la variable
        If Position > 1 Then                          'si la posicion no es uno:
            pl = Right(pl, (Len(pl) - 1))             'extrae desde la derecha la longitud menos uno
            ThisWorkbook.ActiveSheet.Range("d4").Value = pl    'asigna a la celda el nuevo valor
        End If
    Loop Until Position < 2      'repite hasta que la posicion sea menor a 2
    If Position = 1 Then 'si la posicion es 1, ya estan borraos los espacios y sale del for loop
        Exit For
    End If
Next                  'si la posicion es 0, no encontro la opcion, por lo que pasa a testear la siguiente opcion

End Sub

martes, 17 de junio de 2014

R Programming: Como filtrar una columna con la función subset()


> #Si tengo un data frame con las siguientes variables, o columnas:
> names(data)

[1] "Date"    "sulfate" "nitrate" "ID"    

> #Y deseo filtrar los valores de una columna, por ejemplo ID igual a uno:

> subset(data, ID == 1)

        Date sulfate nitrate ID
38    2/3/04    2.58   0.632  1
53   8/13/04    5.52   0.173  1
64  11/17/04    2.21   0.568  1
69   1/16/05    2.30   0.719  1
74   2/27/05    2.75   0.479  1
79    4/4/05    2.18   0.211  1
86   6/15/05    4.85   0.266  1
100  11/6/05    2.41   0.302  1
108 12/24/05    2.24   1.800  1

> #Puedo filtrar por varias columnas a la vez, con el operador y (&) o el o(|)

> subset(data, ID==5 & sulfate >=3)

        Date sulfate nitrate ID
633 10/12/03    5.99   0.428  5
663  7/14/04    3.54   0.576  5
667  8/19/04   12.20   0.223  5
674 10/12/04    3.09   0.466  5
676 10/18/04    3.61   0.372  5
679 10/30/04    7.37   0.590  5

> #Puedo filtrar una columna por un rango de valores con %in%

> subset(data, ID %in% 1:8)

         Date sulfate nitrate ID
38     2/3/04   2.580   0.632  1
53    8/13/04   5.520   0.173  1
64   11/17/04   2.210   0.568  1
69    1/16/05   2.300   0.719  1
74    2/27/05   2.750   0.479  1
79     4/4/05   2.180   0.211  1
86    6/15/05   4.850   0.266  1
100   11/6/05   2.410   0.302  1
108  12/24/05   2.240   1.800  1
182   10/6/03   7.210   0.651  2
184  10/30/03   2.420   0.507  2
190   12/5/03   3.150   0.669  2
201   2/27/04   4.400   0.602  2
204   3/16/04   3.460   0.351  2
219   7/26/04  10.900   0.295  2
234   12/5/04   2.030   1.200  2
237  12/29/04   3.410   1.160  2
240   1/28/05   2.870   1.200  2
244   2/21/05   4.170   0.553  2
247   3/17/05   4.190   0.993  2
260   8/26/05   7.680   0.404  2
264    9/1/05   6.650   0.226  2
273  11/18/05   1.630   0.559  2
356  10/24/03   3.470   0.363  3
358  11/11/03   1.430   0.474  3
374   4/21/04   2.420   0.531  3
399  10/24/04   4.190   0.221  3
404  12/11/04   2.110   0.429  3
408   1/10/05   4.960   0.537  3
411    2/3/05   1.530   0.460  3
418   4/22/05   2.740   0.409  3
419   5/16/05   4.640   0.204  3
423   6/21/05   7.250   0.355  3
429    8/8/05   2.680   0.191  3
442   2/16/06   2.700   1.030  3
510   1/22/04   2.050   1.400  4
515   2/21/04   3.540   0.671  4
517    3/4/04   2.040   0.815  4
535   8/31/04   4.390   0.236  4
550   3/11/05   1.220   0.902  4
552   3/23/05   1.920   0.233  4
559   5/10/05   5.840   0.189  4
566   9/13/05  19.100   0.149  4
583   2/22/06   3.740   0.657  4
633  10/12/03   5.990   0.428  5
643  12/29/03   2.330   0.554  5
654   5/15/04   2.760   0.520  5
662    7/8/04   1.480   0.186  5
663   7/14/04   3.540   0.576  5
665    8/1/04   1.630   0.372  5
667   8/19/04  12.200   0.223  5
674  10/12/04   3.090   0.466  5
676  10/18/04   3.610   0.372  5
679  10/30/04   7.370   0.590  5
682   11/5/04   2.680   0.219  5
686  11/29/04   1.780   0.739  5
697   4/16/05   2.790   0.421  5
707   7/15/05   1.360   0.250  5
722  11/30/05   0.959   0.312  5
725  12/30/05   2.530   1.010  5
792  10/18/03   4.680   1.040  6
798  11/29/03   1.300   0.491  6
805    2/9/04   3.260   0.506  6
809   3/28/04   2.000   0.340  6
822   9/18/04   4.300   0.203  6
823   9/30/04  15.800   0.472  6
831  12/17/04   1.820   0.941  6
833  12/23/04   2.370   0.570  6
840   3/29/05   2.550   0.215  6
842   4/10/05   2.930   0.286  6
845    6/3/05   2.090   0.290  6
854   8/14/05   5.420   0.209  6
858   9/19/05   6.040   0.188  6
860   9/25/05   2.800   0.342  6
872  12/18/05   2.370   1.100  6
943  11/23/03   3.410   0.964  7
945  12/23/03   2.270   0.715  7
954   3/22/04   2.990   0.486  7
965    8/7/04   5.760   0.193  7
984    2/9/05   1.280   0.378  7
991    5/4/05   4.730   0.285  7
994   5/28/05   6.650   0.276  7
1006 12/12/05   0.613   0.326  7
1012  2/10/06   2.600   1.480  7
1076  1/10/04   7.130   0.518  8
1085  7/20/04   6.630   0.118  8
1088  8/25/04   4.980   0.227  8
1103  1/22/05   4.670   1.770  8
1118  6/27/05   3.220   0.205  8
1119   7/3/05   3.810   0.322  8
1122  7/21/05   1.850   0.177  8
1124   8/2/05   2.570   0.503  8
1126  8/20/05   9.520   0.193  8
1131  10/7/05   1.820   0.267  8
1135 11/24/05   1.670   0.743  8
1136  12/6/05   2.740   1.830  8

lunes, 16 de junio de 2014

R Programming: Como combinar multiples archivos en un mismo Dataset

Asumiendo que cada uno de los archivos esté estructurado de forma similar, mismo numero de columnas con los mismos titulos (Los nombres de las columnas se conocen como variables). La clave es hacer un For Loop en el directorio de los archivos y luego irlos combinando las filas con la funcion rbind()

Lo primero que hay que hacer es fijar el working directory al folder donde se encuentran los archivos a combinar, con la funcion setwd("target_dir/")

Luego se obtiene un listado de todos los archivos dentro de ese directorio y se lo carga a una variable. Se usa la funcion:

file_list = list.files()

No es necesario especificar la ruta, toma los archivos del working directory especificado.

Luego se hace un for loop por cada "file" en la variable file_list:



for (file in file_list){
       
  # dataset es la variable donde vamos a ir acumulado los datos
# si no existe la variable, se la crea asignando el valor de la tabla en
# el primer archivo del loop:

  if (!exists("dataset")){
    dataset <- read.table(file, header=TRUE, sep="\t")
  }
   
  # si ya existen datos en la variable dataset, se crea una variable temporal
# donde se van a guardar los datos del archivo corriente en el loop y
# luego se lo une a la variable dataset con la funcion rbind()
# y luego del rbind se borra el contenido de la variable temporal.

  if (exists("dataset")){
    temp_dataset <-read.table(file, header=TRUE, sep="\t")
    dataset<-rbind(dataset, temp_dataset)
    rm(temp_dataset)
  }

}


El articulo completo: http://www.r-bloggers.com/merge-all-files-in-a-directory-using-r-into-a-single-dataframe/