读取一个csv文件并计算值之间的差异,以制作饼图

如何解决读取一个csv文件并计算值之间的差异,以制作饼图

我正在申请一份工作,以记录人们在做什么的时间。 (即有空,忙,现场,返回站点,快速休息,午餐休息)。

发生的事情是,当用户单击按钮时,它将用户名写入文件,然后写入逗号,然后写入时间(小时,分钟和秒)。例如:

{{1}}

我已经弄清楚了如何仅显示用户的状态更新,然后使用以下内容填充到标签中:

{{1}}

如果可能的话,我想做的是找出每个用户花费的时间差,然后用它来在图表中填充饼图,以便它可以显示饼图中每个段的大小,用户在每种状态下花费。因此,在我的代码中,我可以以某种方式计算用户在每种状态下花费的总时间,并以此为基础创建饼图吗?我有一个想法,要读入每一行,然后检查状态并计算出每个状态的变化,然后将其添加到变量中以填充饼图,但无法弄清楚这一点。任何帮助将不胜感激!谢谢。

解决方法

这可以通过在给定状态下汇总每个员工的工期来实现,最好是CSV文件具有列标题,然后可以使用Schema.ini并使用ODBC text driver查询数据,这是最小的可重现示例:

sampledata.csv:

Name,Status,Time
John,Available,10:10:26
Dave,10:15:40
Steve,10:44:14
John,Busy,12:13:28
Steve,QuickBreak,12:15:25
John,12:18:03
Dave,12:18:03
Steve,12:28:16
John,Offline,17:00:00
Dave,17:00:00
Steve,17:00:00

Schema.ini:

[sampledata.csv]
Format=CSVDelimited
ColNameHeader=True
Col1 = "Name" Text
Col2 = "Status" Text
Col3 = "TimeStamp" DateTime

员工类别和状态枚举:

class Employee
{
    public static List<Employee> Employees { get; private set; } = new List<Employee>();
    public string Name { get; }
    public StatusEnum Status { get; }
    public DateTime TimeStamp { get; }
    public TimeSpan Duration { get; private set; }
            

    public Employee(string name,StatusEnum status,DateTime time)
    {
        this.Name = name;
        this.Status = status;
        this.TimeStamp = time;
        Employees.Add(this);
    }

    public static Dictionary<string,double> GetEmployeeStatusSummary(Employee employee)
    {
        var dict = new Dictionary<string,double>();
        foreach (var emp in Employees.Where(e => e.Name == employee.Name))
        {
            if (dict.ContainsKey(emp.Status.ToString()))
            {
                dict[emp.Status.ToString()] += emp.Duration.TotalMinutes;
            }
            else
            {
                dict.Add(emp.Status.ToString(),emp.Duration.TotalMinutes);
            }
        }
        return dict;
    }

    public static void UpdateAllEmployeesDuration()
    {
        Employees = Employees.OrderBy(e => e.Name).ThenBy(e => e.TimeStamp).ToList();
        TimeSpan duration;
        for (int i = 0; i < Employees.Count - 1; i++)
        {
            if (Employees[i].Name == Employees[i + 1].Name)
            {
                duration = Employees[i + 1].TimeStamp - Employees[i].TimeStamp;
                Employees[i].Duration = duration;
            }
        }
    }

    override public string ToString()
    {
        return this.Name;
    }
}

enum StatusEnum
{
    Available,Break,Offline
}

然后在带有饼图的Form中,使用刷新按钮触发流程->查询CSV文件,使用员工姓名更新下拉列表并清除图表,如果CSV文件经常更新并且用户经常使用,则很有用想要查看新数据。 ComboBox事件SelectedIndexChanged将更新图表以显示所选员工的数据。

private void btn_Refresh_Click(object sender,EventArgs e)
{
    var csvPath = Path.GetDirectoryName(Application.ExecutablePath);
    var connStr = "Driver={Microsoft Text Driver (*.txt; *.csv)}; Extensions=asc,csv,tab,txt; Dbq=";
    var dt = new DataTable();

    using (var conn = new OdbcConnection(connStr + csvPath))
    using (var odba = new OdbcDataAdapter("SELECT * FROM sampledata.csv",conn))
    {
        odba.Fill(dt);
    }

    foreach (DataRow row in dt.Rows)
    {
        var name = row[nameof(Employee.Name)].ToString();
        Enum.TryParse(row[nameof(Employee.Status)].ToString(),out StatusEnum status);
        var duration = (DateTime)row[nameof(Employee.TimeStamp)];
        new Employee(name,status,duration);
    }
    Employee.UpdateAllEmployeesDuration();

    this.chart_Pie.Series.Clear();
    this.cbx_Names.DataSource = Employee.Employees.GroupBy(emp => emp.Name)
                                                    .Select(g => g.First())
                                                    .ToList();
}

private void cbx_Names_SelectedIndexChanged(object sender,EventArgs e)
{
    var employee = (Employee)cbx_Names.SelectedItem;
            
    if (this.chart_Pie.Series.IsUniqueName(employee.Name) == false)
    {
        foreach (var series in this.chart_Pie.Series)
        {
            if (series.Name.Equals(employee.Name,StringComparison.OrdinalIgnoreCase))
            {
                series.Enabled = true;
            }
            else
            {
                series.Enabled = false;
            }
        }
    }
    else
    {
        foreach (var ser in this.chart_Pie.Series)
        {
            ser.Enabled = false;
        }
        var points = Employee.GetEmployeeStatusSummary(employee);
        var series = new Series(employee.Name);
        series.ChartType = SeriesChartType.Pie;
        this.chart_Pie.Series.Add(series);
        this.chart_Pie.Series[employee.Name].Points.DataBindXY(points.Keys,points.Values);
    }
}

最后的结果:

enter image description here

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-