use std::{error::Error, fs::File, io::BufReader};
use csv::{ReaderBuilder, StringRecord};
use crate::data_frame::{data_frame::*, data_type::DataType};
pub fn read_csv(file_path : &str , header : bool , category : bool) -> Result<DataFrame, Box<dyn Error>> {
let start_time = std::time::Instant::now();
let mut number_of_samples = 0_u32;
let mut number_of_attributes = 0_u32;
let file_system = File::open(file_path).unwrap();
let reader = BufReader::new(file_system);
let csv_reader = ReaderBuilder::new().has_headers(true).from_reader(reader);
for records in csv_reader.into_records() {
match records {
Ok(_) => number_of_samples += 1,
Err(_) => continue,
};
}
let file_system = File::open(file_path)?;
let reader = BufReader::new(file_system);
let mut csv_reader = ReaderBuilder::new().has_headers(true).from_reader(reader);
let mut data = vec![];
let mut data_type : Vec<u8> = vec![];
if category == false {
for records in csv_reader.records() {
let _result = records?;
for element in _result.iter() { if let Ok(_temp) = element.parse::<f32>() {
data.push(DataType::Floats(vec![0.0_f32 ; number_of_samples as usize]));
data_type.push(0); } else { data.push(DataType::Strings(vec![String::new() ; number_of_samples as usize])); data_type.push(1); }
number_of_attributes += 1;
}
break; }
} else {
for records in csv_reader.records() {
let _result = records?;
for element in _result.iter() {
if let Ok(_temp) = element.parse::<u8>() {
data.push(DataType::Category(vec![0_u8 ; number_of_samples as usize]));
data_type.push(2); } else {
data.push(DataType::Strings(vec![String::new() ; number_of_samples as usize])); data_type.push(1);
}
number_of_attributes += 1;
}
break;
}
}
let file_system = File::open(file_path)?;
let reader = BufReader::new(file_system);
let mut csv_reader = ReaderBuilder::new().has_headers(true).from_reader(reader);
let mut max_vector = return_vector(&data_type, number_of_attributes.try_into().unwrap(), 1);
let mut min_vector = return_vector(&data_type, number_of_attributes.try_into().unwrap() , 0);
let default_parse_fail = 0_u8;
let mut count = 0;
let mut i = 0_usize; csv_reader.records().for_each(|record| {
if let Ok(_result) = record {
for (j , element) in _result.iter().enumerate() {
match data_type[j] {
0 => {
if let DataType::Floats(data_f32) = &mut data[j]{
let temp = element.parse::<f32>().unwrap_or_else(|_| f32::NAN);
data_f32[i] = temp;
if temp < min_vector[j] {
min_vector[j] = temp;
}
if temp > max_vector[j] {
max_vector[j] = temp;
}
}
},
1 => {
if let DataType::Strings(data_string) = &mut data[j] {
data_string[i] = element.to_owned();
}
},
2 => {
if let DataType::Category(data_vec_u8) = &mut data[j] {
let temp = element.parse::<u8>().unwrap_or_else(|_| default_parse_fail); data_vec_u8[i] = temp;
let temp_now = temp as f32;
if temp_now < min_vector[j] {
min_vector[j] = temp_now;
}
if temp_now > max_vector[j] {
max_vector[j] = temp_now;
}
}
},
_ => {}
}
}
i += 1;
} else {
count += 1;
};
});
let mut headers = vec![String::new() ; number_of_attributes.try_into().unwrap()];
if header {
let file_system = File::open(file_path)?;
let reader = BufReader::new(file_system);
let mut csv_reader = ReaderBuilder::new().has_headers(true).from_reader(reader);
let temp2 = StringRecord::default();
let _result = csv_reader.headers().unwrap_or({println!("Parsing headers failed"); &temp2});
for (i , name) in _result.iter().enumerate() {
headers[i] = _result.get(i).unwrap_or(" ").to_owned();
}
} else {
for i in 0..number_of_attributes {
let name = format!( "column{}", i);
headers[i as usize] = name;
}
}
let data_frame_ = DataFrame {
data,
headers,
max_vector,
min_vector,
number_of_features: number_of_attributes,
number_of_samples,
normalized: false,
};
println!("parsing failed at {} strings", count);
println!("Time taken to load the csv as DataFrame into the memory is : {:?}", start_time.elapsed());
Ok(data_frame_)
}
fn return_vector(data_type : &Vec<u8> , size : usize , max_min : u8) -> Vec<f32> {
let mut new_vec = if max_min == 0 {
vec![f32::MAX ; size]
} else {
vec![f32::MIN ; size]
};
for i in 0..size {
if data_type[i] == 1 {
new_vec[i] = f32::NAN; }
}
new_vec
}