Как перенести код Python, который определяет, к какому заголовку CSV принадлежит значение, спрашивая «можно ли превратить его в число»? - PullRequest
0 голосов
/ 10 сентября 2018

Значения - это, по сути, столбцы в CSV, которые отображаются в одном столбце. Чтобы понять, к какому заголовку относится значение, я просто говорю «можно ли превратить его в число».

Самый простой пример того, что я пытаюсь сделать в Python:

data = ["a","1","2","3","b","4","5","6","c","7","8","9"]

class treatment:
    def __init__(self, name):
        self.name = name
        self.data = []

results = []

for d in data:
    try:
        int(d)
    except ValueError:
        results.append(treatment(name=d))
    else:
        results[-1].data.append(d)

Это то, что у меня есть в Rust, но не работает после разбора:

extern crate csv;

use std::error::Error;
use std::fs::File;
use std::io;
use std::prelude::v1::Option;
use std::process;
use std::vec::Vec;

struct Treatment {
    raw_name: String,
    channel: String,
    data: Vec<i64>,
}

impl Treatment {
    fn observe(&mut self, observation: i64) {
        &mut self.data.push(observation);
    }
}

struct Experiment {
    treatments: Vec<Treatment>,
}

impl Experiment {
    fn add_treatment(&mut self, treatment_name: &str, channel: &str) {
        &mut self.treatments.push(Treatment {
            raw_name: treatment_name.to_string(),
            channel: channel.to_string(),
            data: Vec::new(),
        });
    }

    fn get_current_experiment(&mut self) -> &Treatment {
        self.treatments.last().unwrap()
    }
}

fn deserialize_csv(file_path: String) -> csv::Reader<File> {
    csv::ReaderBuilder::new()
        .has_headers(false)
        .from_path(file_path)
        .expect("Experienced issues reading csv file")
}

fn vectorize_string_records(mut csv_reader: csv::Reader<File>) {
    let mut experiments: Experiment = Experiment {
        treatments: Vec::new(),
    };

    for row in csv_reader.records() {
        // for these datasets we only care about data in the first cell
        let datapoint = match &row {
            Ok(T) => T.get(0),
            Err(E) => Some(""),
        }.unwrap();

        let val_as_int = datapoint.parse::<i64>();

        let current_treatment = experiments.get_current_experiment();

        // discern if value is header or datapoint
        match val_as_int {
            Ok(int_val) => &current_treatment.observe(int_val),
            Err(new_header) => &experiments.add_treatment(datapoint, &"ch=1".to_string()),
        };

        println!("{}", datapoint);
    }
}

fn main() {
    let i = deserialize_csv("/home/file.csv".to_string());
    vectorize_string_records(i);
}

Я борюсь с несколькими концепциями, пытаясь реализовать это в Rust.

Ответы [ 2 ]

0 голосов
/ 10 сентября 2018

Предположим, file.csv отформатирован как один столбец, содержащий столбцы с накоплением:

a
1
2
b
2
3

Это фрагмент, который читает из такого файла CSV и копирует логику Python.

В нем используется подход, основанный на итераторах, с использованием комбинатора fold для накопления данных об обработке:

extern crate csv;

#[derive(Debug)]
struct Treatment {
    name: String,
    data: Vec<i32>,
}

impl Treatment {
    fn new(name: String) -> Self {
        Self {
            name,
            data: Vec::new(),
        }
    }
}

fn read_csv(file_path: String) -> Vec<Treatment> {
    let mut reader = csv::ReaderBuilder::new()
        .has_headers(false)
        .from_path(file_path)
        .expect("error reading csv file");

    reader
        .records()
        .fold(Vec::new(), |mut treatments: Vec<Treatment>, item| {
            match item {
                Ok(str_record) => {
                    let item = str_record.get(0).expect("missing column value");
                    match item.parse::<i32>() {
                        Ok(n) => treatments
                            .last_mut()
                            .expect("expected a header in the first row")
                            .data
                            .push(n),
                        Err(_) => treatments
                            .push(Treatment::new(item.to_string())),
                    }
               }
               Err(err) => panic!("error: {}", err),
            }
            treatments
        })
}

fn main() {
    let treatments = read_csv("./file.csv".to_string());
    println!("got: {:?}", treatments);
}
0 голосов
/ 10 сентября 2018

Буквальный порт вашего кода Python для Rust:

#[derive(Debug)]
struct Treatment {
    name: String,
    data: Vec<i32>,
}

impl Treatment {
    fn new(name: String) -> Self {
        Self {
            name,
            data: Vec::new(),
        }
    }
}

fn main() {
    let data = ["a", "1", "2", "3", "b", "4", "5", "6", "c", "7", "8", "9"];
    let mut results: Vec<Treatment> = Vec::new();
    for d in &data {
        if let Ok(n) = d.parse::<i32>() {
            let last = results
                .last_mut()
                .expect("Some header must come before the values");
            last.data.push(n);
        } else {
            results.push(Treatment::new(d.to_string()))
        }
    }
    println!("results = {:#?}", results);
}

Детская площадка

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...