From 3ab79b3f47cfbff0f1c6ae4211defa8e935328cf Mon Sep 17 00:00:00 2001 From: vicgq Date: Fri, 1 Nov 2024 20:56:47 -0600 Subject: [PATCH] =?UTF-8?q?MovieLens=20(Go)=20Laboratorio=20de=20implement?= =?UTF-8?q?aci=C3=B3n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Solución al ejercicio de 'Movielens' utilizando goroutines. --- movielens.go | 269 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 269 insertions(+) create mode 100644 movielens.go diff --git a/movielens.go b/movielens.go new file mode 100644 index 00000000..f6debca9 --- /dev/null +++ b/movielens.go @@ -0,0 +1,269 @@ +package main + +import ( + "os" + "fmt" + "log" + "sync" + "time" + "strings" + "strconv" + "encoding/csv" + + "github.com/kfultz07/go-dataframe" +) + +type RatingObj struct { + UserId int64 + movieId int64 + rating float64 + Timestamp int64 +} + +func main() { + var dir, file string + var chunkNumber int + var chunkData [][]string + + var startTotalTime = time.Now() + dir = "movielens" + directory := MakeDir(dir) + fmt.Println("Los archivos de salida se guardarán en el directorio:", dir) + + var startTime = time.Now() + file = "ratings" + data := readCSV(file) + fmt.Printf("El archivo a particionar es '%s', contiene '%d' lineas en total", file, len(data)) + fmt.Println("\ny tomó", time.Since(startTime).Seconds(), "segundos en leer el numero de lineas.") + + chunkNumber = 10 + numLineas := len(data)/chunkNumber + fmt.Printf("\nEl archivo '%s' se dividirá en '%d' subarchivos",file,chunkNumber) + fmt.Printf("\ny cada subarchivo tendrá '%d' lineas.\n",numLineas) + + var wg sync.WaitGroup // Numero de gorutinas trabajando + startTime = time.Now() + chunkName := make(chan string) + for i:=0; i RESULTADOS <======================") + // Calcular y mostrar el promedio de ratings por género + for i := 0; i < ng; i++ { + avgRating := 0.0 + if locCount[i] > 0 { + avgRating = locVals[i] / float64(locCount[i]) + } + fmt.Println(fmt.Sprintf("%2d", i), " ", fmt.Sprintf("%20s", kg[i]), " ", fmt.Sprintf("%8d", locCount[i]), " ", fmt.Sprintf("Avg Rating: %.2f", avgRating)) + } + + duration := time.Since(start) + fmt.Println("\n\nDuración de ejecución de 'Mt_FindRatingsMaster'", duration) + println("'Mt_FindRatingsMaster' terminó") +} + +func Mt_FindRatingsWorker(w int, file string, directory string, ci chan int, kg []string, ca *[][]int, va *[][]float64, movies dataframe.DataFrame) { + aFileName := file + "_" + fmt.Sprintf("%01d", w) + ".csv" + println("El worker " , fmt.Sprintf("%01d", w), " está procesando el archivo ", aFileName) + + ratings := ReadRatingsCsvFile(directory, aFileName) + ng := len(kg) + start := time.Now() + + ratings.Merge(&movies, "movieId", "genres") + + grcs := [2]string{"genres", "rating"} + grDF := ratings.KeepColumns(grcs[:]) + for ig := 0; ig < ng; ig++ { + for _, row := range grDF.FrameRecords { + if strings.Contains(row.Data[0], kg[ig]) { + (*ca)[ig][w] += 1 + v, _ := strconv.ParseFloat((row.Data[1]), 32) + (*va)[ig][w] += v + } + } + } + duration := time.Since(start) + fmt.Println("El worker ", w," terminó con una duración de ", duration) + + ci <- 1 +} + +// Función para leer el archivo de películas +func ReadMoviesCsvFile(filePath string, fileOb string) dataframe.DataFrame { + // Abrir el archivo + file, err := os.Open(filePath) + if err != nil { + log.Fatalf("Error al abrir el archivo %s: %v", filePath, err) + } + defer file.Close() + + // Leer el CSV y devolver el DataFrame + return dataframe.CreateDataFrame(filePath, fileOb) +} + +// Función para leer el archivo de ratings +func ReadRatingsCsvFile(directory string, fileOb string) dataframe.DataFrame { + // Abrir el archivo + file, err := os.Open(directory) + if err != nil { + log.Fatalf("Error al abrir el archivo %s: %v", directory, err) + } + defer file.Close() + + // Leer el CSV y devolver el DataFrame + return dataframe.CreateDataFrame(directory, fileOb) +} + +func spinner(delay time.Duration) { + for { + for _, r := range `-\|/` { + fmt.Printf("\r %c", r) + time.Sleep(delay) + } + } +} \ No newline at end of file