首页 > 解决方案 > Python:GPS 点和属性的数据结构和处理

问题描述

我正在尝试从 csv 读取数据,然后以不同的方式处理它。(对于初学者来说只是平均水平)

数据
(OneDrive) https://1drv.ms/u/s!ArLDiUd-U5dtg0teQoKGguBA1qt9?e=6wlpko

数据如下所示:
ID;财产1;财产2;属性3...
1; ....
1; ...
1; ...
2; ...
2; ...
3; ……

每条线路都是一个 GPS 点具有相同 ID 的所有点(例如 1)一起生成一条路线。这些路线的长度不同,并且跳过了一些 ID。所以这不是数字的无缝增加。

我可能需要补充一点,这些点总是彼此相距相同的一组米。而且我目前不需要 XY 信息。

想要的结果
最后我想要这样的东西: [ID, AVG_Property1, AVG_Property2...] [1, 1.00595, 2.9595, ...] [2,1.50606, 1.5959, ...]

到目前为止我得到了什么

import os
import numpy
import pandas as pd
data = pd.read_csv(os.path.join('C:\\data' ,'data.csv'), sep=';')
# [id, len, prop1, prop2, ...]
routes = numpy.zeros((data.size, 10)) # 10 properties

sums = numpy.zeros(8)
nr_of_entries = 0;
current_id = 1;

for index, row in data.iterrows():
    if(int(row['id']) != current_id): #after the last point of the route
        routes[current_id-1][0] = current_id;
        routes[current_id-1][1] = nr_of_entries; #how many points are in this route?
        routes[current_id-1][2] = sums[0] / nr_of_entries;
        routes[current_id-1][3] = sums[1] / nr_of_entries;
        routes[current_id-1][4] = sums[2] / nr_of_entries;
        routes[current_id-1][5] = sums[3] / nr_of_entries;
        routes[current_id-1][6] = sums[4] / nr_of_entries;
        routes[current_id-1][7] = sums[5] / nr_of_entries;
        routes[current_id-1][8] = sums[6] / nr_of_entries;
        routes[current_id-1][9] = sums[7] / nr_of_entries;

        current_id = int(row['id']);
        sums = numpy.zeros(8)
        nr_of_entries = 0;

    sums[0] += row[3];
    sums[1] += row[4];
    sums[2] += row[5];
    sums[3] += row[6];
    sums[4] += row[7];
    sums[5] += row[8];
    sums[6] += row[9];
    sums[7] += row[10];
    nr_of_entries = nr_of_entries + 1;

routes

我的问题
1.) 我这样做的方式,我必须为所有其他处理方法复制粘贴相同的代码,因为如上所述我需要做多种不同的方式。平均只是一个例子。

2.)数据的读取很笨拙,并且在缺少 ID 时会失败

3.) 我是 C# 开发人员,所以我的方法是创建一个包含所有点的“路线”类,然后提供“计算道具 1 的平均值”的方法。或者其他的东西。这样我还可以根据需要调整数据。(例如极端值)。但我不知道这将如何在 Phyton 中完成,以及这是否是这种语言的合理方法。

4.) 是否有更优雅的方式来遍历原始 csv 并获得类似 Route ID 1,然后是 Route ID 2 等等?可能类似于 C# 中的 LINQ 查询?

谢谢你的帮助。

标签: pythonarraysdata-structuresaverage

解决方案


他是一个解决方案和一些你可以使用的想法。该示例为同一问题提供了多个选项,因此您必须选择最适合目的的选项。它也是 Python 3.7,你没有指定版本,所以我希望这能工作。

class Route(object):
    """description of class"""
    def __init__(self, id, rawdata): # on startup
        self.id = id
        self.rawdata = rawdata
        self.avg_Prop1 = self.calculate_average('Prop1')
        self.sum_Prop4 = None 

    def calculate_average(self, Prop_Name): #selfreference for first argument in class method
        return self.rawdata[Prop_Name].mean()

    def give_Prop_data(self, Prop_Name): #return the Propdata as list
        return self.rawdata[Prop_Name].tolist()

    def any_function(self, my_function, Prop_Name): #not sure what dataframes support so turning it into a list first
        return my_function(self.rawdata[Prop_Name].tolist())

#end of class definiton


data = pd.read_csv('testdata.csv', sep=';')
# [id, len, prop1, prop2, ...]


route_list = [] #List of all the objects created from the route class
for i in data.id.unique():
    print('Current id:', i,' with ',len(data[data['id']==i]),'entries')
    route_list.append(Route(i,data[data['id']==i]))


#created the Prop1 average in initialization of route so just accessing attribute
print(route_list[1].avg_Prop1)

for current_route in route_list:
    print('Route ',current_route.id , ' Properties :')
    for i in current_route.rawdata.columns[1:]: #for all except the first (id)
        print(i, ' has average ', current_route.calculate_average(i)) #i is the string of the column not just an id

#or pass any function that you want
route_list[1].sum_Prop4 = (route_list[1].any_function(sum,'Prop4'))
print(route_list[1].sum_Prop4)
#which is equivalent to
print(sum(route_list[1].rawdata['Prop4']))

要解决您的个人问题,请执行以下操作:

对于 2. 和 4.) 仅在现有 Id ( data.id.unique()) 上循环可以解决问题。我不知道 LINQ 查询是什么,但我认为它们是相似的。一般来说,Python 有一种很好的循环对象的方法(比如for current_route in route_list),如果你想多用一点,那么值得研究一下。

对于 1. 和 3.) 再次循环解决了这个问题。我在示例中创建了一个类,主要是为了显示类的语法。在 Python 中使用类的优点和缺点应该与在 C# 中相同。

因为现在这个类可能不是很好,但这取决于你想如何使用它。如果该类应该只是一种存储和访问数据的实用方法,那么它不应该具有方法,因为您不需要average为每条路由使用单独的方法。然后,您可以访问它的数据并在类似 in 的函数中使用它sum(route_list[1].rawdata['Prop4'])。但是,如果需要根据数据(例如行数)进行不同的计算,则使用该方法calculate_average并在其中进行区分可能会派上用场。

另一个例子是属性的使用。如果您每次都需要 Prop1 的平均值,那么在初始化时创建它是一个好主意,否则我不会一直计算它。

我希望这有帮助!


推荐阅读