Začnime teda vylepšením kódu v jazyku R:

  1. Pomenovanie premenných: Premenujte premenné tak, aby boli v súlade so štandardom camelCase.
  2. Indentácia: Používanie jedného štýlu odsadenia (zvyčajne 2 alebo 4 medzery). Zvyčajne sa odporúčajú 2 medzery.
  3. Medzery: Pridanie medzier okolo operátorov na zlepšenie čitateľnosti.
  4. Komentáre: Pridanie komentárov na sprehľadnenie kódu.
  5. Formátovanie riadkov: Používanie jedného štýlu na formátovanie reťazcov.

Pomenovanie premenných

viac…
# 1. Odhad strednej hodnoty dojazdu automobilov
meanMpgMtcars <- mean(mtcars$mpg)
print(paste("Stredná hodnota dojazdu automobilov:", meanMpgMtcars))
## [1] "Stredná hodnota dojazdu automobilov: 20.090625"
# 2. Odhad strednej hodnoty dojazdu v závislosti od zdvihového objemu valcov (lineárny regresný model)
mpgModelMtcars <- lm(mpg ~ disp, data = mtcars)

# Vizualizácia modelu
ggplot(mtcars, aes(x = disp, y = mpg)) +
  geom_point() +
  geom_smooth(method = "lm", se = FALSE) +
  labs(x = "Zdvihový objem valcov", y = "Dojazd (MPG)")
## `geom_smooth()` using formula = 'y ~ x'

# 3. Rozšírenie modelu o počet valcov
mpgModelWithCylindersMtcars <- lm(mpg ~ disp + cyl, data = mtcars)

# Vizualizácia modelu s počtom valcov
ggplot(mtcars, aes(x = disp, y = mpg, color = factor(cyl))) +
  geom_point() +
  geom_smooth(method = "lm", se = FALSE) +
  labs(x = "Zdvihový objem valcov", y = "Dojazd (MPG)", color = "Počet valcov")
## `geom_smooth()` using formula = 'y ~ x'

# 4. Interakcia medzi objemom valcov a počtom valcov
mpgModelInteractionMtcars <- lm(mpg ~ disp * cyl, data = mtcars)

# Vizualizácia interakcie
ggplot(mtcars, aes(x = disp, y = mpg, color = factor(cyl))) +
  geom_point() +
  geom_smooth(method = "lm", se = FALSE, aes(group = cyl)) +
  labs(x = "Zdvihový objem valcov", y = "Dojazd (MPG)", color = "Počet valcov")
## `geom_smooth()` using formula = 'y ~ x'

# 5. Priemerný dojazd štvorvalcového automobilu podľa posledného modelu
mtcars$predictedMpg <- predict(mpgModelInteractionMtcars, mtcars)
maxMpgCarMtcars <- mtcars[which.max(mtcars$predictedMpg), ]
print(paste("Priemer dojazdu štvorvalcového automobilu:", mean(maxMpgCarMtcars$mpg)))
## [1] "Priemer dojazdu štvorvalcového automobilu: 33.9"
# 6. Zmena odpovede pri použití komplexnejšieho súboru údajov (auto-mpg.data)
autoMpgFull <- read.table("./Rk/auto/auto-mpg.data", header = FALSE, sep = "", na.strings = "?")
colnames(autoMpgFull) <- c("mpg", "cylinders", "displacement", "horsepower", "weight", "acceleration", "modelYear", "origin", "carName")
mpgModelInteractionFull <- lm(mpg ~ displacement * cylinders, data = autoMpgFull)
autoMpgFull$predictedMpg <- predict(mpgModelInteractionFull, autoMpgFull)
maxMpgCarFull <- autoMpgFull[which.max(autoMpgFull$predictedMpg), ]
print(paste("Priemer dojazdu štvorvalcového automobilu (komplexný dataset):", mean(maxMpgCarFull$mpg)))
## [1] "Priemer dojazdu štvorvalcového automobilu (komplexný dataset): 19"
# 7. Porovnanie modelov podľa RMSE
rmseValues <- c(
  sqrt(mean((predict(mpgModelMtcars, mtcars) - mtcars$mpg)^2)),
  sqrt(mean((predict(mpgModelWithCylindersMtcars, mtcars) - mtcars$mpg)^2)),
  sqrt(mean((predict(mpgModelInteractionMtcars, mtcars) - mtcars$mpg)^2)),
  sqrt(mean((predict(mpgModelInteractionFull, autoMpgFull) - autoMpgFull$mpg)^2))
)

# Poradie modelov podľa RMSE
rankedModels <- c("Model 1", "Model 2", "Model 3", "Model 4")
names(rmseValues) <- rankedModels
print(rmseValues)
##  Model 1  Model 2  Model 3  Model 4 
## 3.148207 2.908717 2.488103 4.441170
# Predikcia priemerneho dojazdu štvorvalcového automobilu so zdvihovým objemom 160 kubických palcov
predictedMpg <- predict(mpgModelInteractionFull, data.frame(displacement = 160, cylinders = 4))
print(paste("Predikovaný dojazd štvorvalcového automobilu so zdvihovým objemom 160 kubických palcov:", predictedMpg))
## [1] "Predikovaný dojazd štvorvalcového automobilu so zdvihovým objemom 160 kubických palcov: 24.5494704620028"
# 8. Model závislosti dojazdu iba od zdvihového objemu s vhodnou transformáciou
mpgModelDisplacementOnly <- lm(mpg ~ log(displacement), data = autoMpgFull)

# Vizualizácia modelu
ggplot(autoMpgFull, aes(x = displacement, y = mpg)) +
  geom_point() +
  geom_smooth(method = "lm", formula = y ~ log(x), se = FALSE) +
  labs(x = "Zdvihový objem valcov", y = "Dojazd (MPG)")

Teraz prepíšeme ten istý kód do jazyka C:

viac…

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

// Štruktúra na reprezentáciu údajov o vozidle
typedef struct {
    double mpg;
    int cylinders;
    double displacement;
    double weight;
} CarData;

// Funkcia na čítanie údajov o aute zo súboru
int readCarData(const char *filename, CarData **cars) {
    FILE *file = fopen(filename, "r");
    if (file == NULL) {
        printf("Error: Unable to open file '%s'\n", filename);
        return -1;
    }

    int numCars = 0;
    *cars = NULL;
    char line[1000];
    while (fgets(line, sizeof(line), file) != NULL) {
        double mpg, displacement, weight;
        int cylinders;
        if (sscanf(line, "%lf %d %lf %lf", &mpg, &cylinders, &displacement, &weight) == 4) {
            (*cars) = realloc(*cars, (numCars + 1) * sizeof(CarData));
            (*cars)[numCars].mpg = mpg;
            (*cars)[numCars].cylinders = cylinders;
            (*cars)[numCars].displacement = displacement;
            (*cars)[numCars].weight = weight;
            numCars++;
        }
    }

    fclose(file);
    return numCars;
}

// Funkcia na výpočet priemernej hodnoty
double calculateMean(double *data, int length) {
    double sum = 0.0;
    for (int i = 0; i < length; i++) {
        sum += data[i];
    }
    return sum / length;
}

// Funkcia na výpočet priemerného dojazdu áut
double calculateMeanMpg(CarData* cars, int numCars) {
    double* mpg = (double*)malloc(numCars * sizeof(double));
    if (mpg == NULL) {
        printf("Error: Unable to allocate memory\n");
        return -1.0; // Возвращаем ошибку
    }

    // Naplňte pole mpg hodnotami mpg každého vozidla
    for (int i = 0; i < numCars; i++) {
        mpg[i] = cars[i].mpg;
    }

    double meanMpg = calculateMean(mpg, numCars);

    // Uvoľnenie alokovanej pamäte
    free(mpg);

    return meanMpg;
}


int main() {
    // Čítanie údajov zo súboru
    CarData *cars;
    int numCars = readCarData("./Rk/auto/auto-mpg.data", &cars);
    if (numCars == -1) {
        return 1;
    }

    // Výpočet priemerného dojazdu automobilov
    double meanMpg = calculateMeanMpg(cars, numCars);
    printf("Stredná hodnota dojazdu automobilov: %.2f\n", meanMpg);

    // Uvoľnenie pamäte
    free(cars);

    return 0;
}

Môj kód je v jazyku C:

viac…
#include <stdlib.h>
#include <stdio.h>

typedef struct {
    int* arr;
    size_t size;
    size_t cop;
}Vec;

void constructor(Vec* obj,const size_t size) {
    obj->size = size;
    obj->cop = size + 1;
    obj->arr = (int*)malloc(obj->cop * sizeof(int));
}

void destructor(Vec* obj) {
    free(obj->arr);
}

void push_back(Vec* obj, int number) {
    if (obj->cop > obj->size) {
        obj->arr[obj->size] = number;
    }
    else {
        obj->cop += 2;
        int* temp = (int*)malloc(obj->cop * sizeof(int));
        for (size_t i = 0; i < obj->size; i++)
        {
            temp[i] = obj->arr[i];
        }
        free(obj->arr);
        obj->arr = temp;
        obj->arr[obj->size] = number;
    }
    obj->size++;
}

void print(Vec obj) {
    for (size_t i = 0; i < obj.size; i++)
    {
        printf("%d ", obj.arr[i]);
    }
    printf("\n");;
}

typedef struct {
    Vec counters;
}Stat_intersectrion;

Vec intersection(Vec obj1, Vec obj2,int** counter) {
    Vec result;
    constructor(&result, 0);
    int counter1 = 0;
    for (size_t obj1_index = 0; obj1_index < obj1.size; obj1_index++)
    {
        counter1++;
        for (size_t obj2_index = 0; obj2_index < obj2.size; obj2_index++)
        {
            counter1++;
            if (obj1.arr[obj1_index] == obj2.arr[obj2_index]) {
                counter1++;
                short flag = 1;
                for (size_t res_index = 0; res_index < result.size; res_index++)
                {
                    counter1++;

                    if (obj1.arr[obj1_index] == result.arr[res_index]) {
                        counter1++;
                        flag = 0;
                        break;
                    }
                }
                if (flag) {
                    push_back(&result, obj1.arr[obj1_index]);
                    break;
                }
            }
        }
    }

    *counter = counter1;
    return result;
}

Vec association(Vec obj1, Vec obj2, int** counter) {
    Vec result;
    constructor(&result, 0);
    int counter1 = 0;

    for (size_t obj1_index = 0; obj1_index < obj1.size; obj1_index++)
    {
        counter1++;
        short flag = 1;
        for (size_t res_index = 0; res_index < result.size; res_index++)
        {
            counter1++;
            if (obj1.arr[obj1_index] == result.arr[res_index]) {
                counter1++;
                flag = 0;
                break;
            }
        }
        if (flag) {
            push_back(&result, obj1.arr[obj1_index]);
        }
    }

    for (size_t obj2_index = 0; obj2_index < obj2.size; obj2_index++)
    {
        counter1++;
        short flag = 1;
        for (size_t res_index = 0; res_index < result.size; res_index++)
        {
            counter1++;
            if (obj2.arr[obj2_index] == result.arr[res_index]) {
                counter1++;
                flag = 0;
                break;
            }
        }
        if (flag) {
            push_back(&result, obj2.arr[obj2_index]);
        }
    }
    *counter = counter1;
    return result;
}

Vec Sum_mnoz(Vec* vec_arr,size_t size) {
    Vec result;
    constructor(&result, 0);

    for (size_t i = 0; i < size; i++)
    {
        for (size_t j = 0; j < vec_arr[i].size; j++)
        {
            push_back(&result, vec_arr[i].arr[j]);
        }
    }
    return result;
}

void draw_graf(Vec obj,const char* filename) {
    FILE* file = fopen(filename, "w");

    for (int i = 0; i < obj.size; i++)
    {
        fprintf(file,"%d\n",obj.arr[i]);
    }
    fclose(file);
}

int main() {
    srand(time(NULL));

    Vec mnoz1 = { NULL},  mnoz2 = { NULL};

    Stat_intersectrion stat;
    Stat_intersectrion stat2;
    constructor(&stat.counters, 0);
    constructor(&stat2.counters, 0);
    int* counter = 0;
    int* counter2 = 0;
    for (size_t i = 1; i <=50; i++)
    {
        

        destructor(&mnoz1);
        destructor(&mnoz2);
        constructor(&mnoz1, 0);
        constructor(&mnoz2, 0);

        for (size_t j = 0; j < i; j++)
        {
            push_back(&mnoz1, rand() % 100);
            push_back(&mnoz2, rand() % 100);
        }

        Vec intersection_res = intersection(mnoz1, mnoz2, &counter);
        push_back(&stat.counters, counter);

        Vec association_res = association(mnoz1, mnoz2, &counter2);
        push_back(&stat2.counters, counter2);
    }
    counter = 0;
    counter2 = 0;
    free(counter);
    free(counter2);
    draw_graf(stat.counters,"intersection.txt");
    draw_graf(stat2.counters,"association.txt");

    destructor(&stat.counters);
    destructor(&mnoz1);
    destructor(&mnoz2);
}

Tento kód v jazyku C bol upravený na riešenie podobného problému a obsahuje funkcie na prácu s vektormi a výpočet priesečníka a zjednotenia množín.

Teraz ho prepíšeme do jazyka R:

viac…
set.seed(Sys.time())

intersection <- function(vec1, vec2) {
  result <- integer(0)
  counter <- 0
  for (i in vec1) {
    counter <- counter + 1
    if (i %in% vec2) {
      counter <- counter + 1
      if (!(i %in% result)) {
        result <- c(result, i)
      }
    }
  }
  return(list(result = result, counter = counter))
}

association <- function(vec1, vec2) {
  result <- integer(0)
  counter <- 0
  for (i in vec1) {
    counter <- counter + 1
    if (!(i %in% result)) {
      result <- c(result, i)
    }
  }
  for (i in vec2) {
    counter <- counter + 1
    if (!(i %in% result)) {
      result <- c(result, i)
    }
  }
  return(list(result = result, counter = counter))
}

drawGraf <- function(obj, filename) {
  write.table(obj, filename, row.names = FALSE, col.names = FALSE)
}

mnoz1 <- integer(0)
mnoz2 <- integer(0)
stat_counters <- integer(0)
stat2_counters <- integer(0)
counter <- 0
counter2 <- 0

for (i in 1:50) {
  mnoz1 <- sample(

1:100, i, replace = TRUE)
  mnoz2 <- sample(1:100, i, replace = TRUE)
  
  intersection_res <- intersection(mnoz1, mnoz2)
  stat_counters <- c(stat_counters, intersection_res$counter)
  
  association_res <- association(mnoz1, mnoz2)
  stat2_counters <- c(stat2_counters, association_res$counter)
}

drawGraf(stat_counters, "intersection.txt")
drawGraf(stat2_counters, "association.txt")

Výpočet priemeru najazdených kilometrov a práca s SQLite databázou

Začnime výpočtom priemerného počtu najazdených kilometrov vozidiel zo súboru údajov mtcars ako funkcie počtu valcov. Na tento účel použijeme balík dplyr na vykonávanie operácií s údajmi a balík parallel na paralelné vykonávanie výpočtov.

# Rozdelenie údajov podľa počtu valcov
mtcars_split <- mtcars %>% split(.$cyl)

# Funkcia na výpočet priemernej prejdenej vzdialenosti
calc_mean_mpg <- function(df) {
  mean(df$mpg)
}

# Paralelné spúšťanie výpočtov
cluster <- makeCluster(detectCores())  # Vytvorenie klastra
clusterExport(cluster, c("calc_mean_mpg"))  # Export funkcie do klastra
mean_mpg <- parSapply(cluster, mtcars_split, calc_mean_mpg)  # Vypočítajte priemerný počet kilometrov pre každý počet valcov
stopCluster(cluster)  # Zastavenie klastra

# Výstup výsledkov
print(mean_mpg)
##        4        6        8 
## 26.66364 19.74286 15.10000

Teraz rozdeľte súbor údajov mtcars na dve tabuľky s rôznymi stĺpcami a uložte ich do databázy SQLite.

# Vytvorenie tabuliek mtcars_part1 a mtcars_part2
mtcars_part1 <- mtcars %>% select(mpg, cyl, disp)
mtcars_part2 <- mtcars %>% select(mpg, hp, wt)

# Pripojenie k databáze SQLite
con <- dbConnect(RSQLite::SQLite(), "mtcars_db.sqlite")

# Prepíšte tabuľky, ak už existujú
dbWriteTable(con, "mtcars_part1", mtcars_part1, row.names = FALSE, overwrite = TRUE)
dbWriteTable(con, "mtcars_part2", mtcars_part2, row.names = FALSE, overwrite = TRUE)

# Zatvorte pripojenie k databáze
dbDisconnect(con)

Teraz sa pripojíme k databáze, spojíme tieto dve tabuľky do jednej a vypíšeme údaje pre všetky vozidlá so šiestimi valcami uložené priamo v databáze.

# Pripojenie k databáze SQLite
con <- dbConnect(RSQLite::SQLite(), "mtcars_db.sqlite")

# Výstupné údaje pre všetky vozidlá so šiestimi valcami
six_cyl_cars <- dbGetQuery(con, "SELECT * FROM mtcars_part1 
                                 INNER JOIN mtcars_part2 
                                 ON mtcars_part1.mpg = mtcars_part2.mpg
                                 WHERE mtcars_part1.cyl = 6")

# Výstup výsledku
print(six_cyl_cars)
##     mpg cyl  disp  mpg  hp    wt
## 1  21.0   6 160.0 21.0 110 2.620
## 2  21.0   6 160.0 21.0 110 2.875
## 3  21.0   6 160.0 21.0 110 2.620
## 4  21.0   6 160.0 21.0 110 2.875
## 5  21.4   6 258.0 21.4 109 2.780
## 6  21.4   6 258.0 21.4 110 3.215
## 7  18.1   6 225.0 18.1 105 3.460
## 8  19.2   6 167.6 19.2 123 3.440
## 9  19.2   6 167.6 19.2 175 3.845
## 10 17.8   6 167.6 17.8 123 3.440
## 11 19.7   6 145.0 19.7 175 2.770
# Zatvorte pripojenie k databáze
dbDisconnect(con)

To je všetko, teraz máme v databáze uložený priemerný rozsah kilometrov pre rôzne počty valcov a údaje pre vozidlá so šiestimi valcami.