【问题标题】:From CSV, group similar data together?从 CSV 中,将相似的数据组合在一起?
【发布时间】:2018-07-27 21:38:13
【问题描述】:

我有一些数据要组合在一起:

Serial_Num     Latitude Longitude
1950004S11059   -11.1   59.1
1950004S11059   -11.6   57.8
1950004S11059   -12.4   56
1950004S11059   -13.2   54.6
1950004S11059   -13.8   53.8
1950004S11059   -14.8   52.7
1950004S11059   -15.9   52
1950004S11059   -18.3   52.4
1950004S11059   -20     54
1950004S11059   -22.1   55.9
1950004S11059   -26.2   59.8
1950012S14150   -14     146.9
1950012S14150   -14.4   145.8
1950012S14150   -14.9   145.4
1950012S14150   -15.8   145.6
1950012S14150   -18.9   149.1
1950012S14150   -22.3   152.5
1950013S14139   -16     139
1950013S14139   -16.3   139

很简单,对于每个唯一的Serial_Num,我想要坐标。我期待类似的东西:

1950004S11059: {"GPS": (-11.1 , 59.1) , (-11.6, 57.8) , (-12.4, 56), ..., (-26.2, 59.8)}

然后我可以循环遍历每个Serial_NumGPS 坐标并进行绘图。

我有一些我在其他地方使用过的脚本,但主要依赖于用于设置字典的 .csv 数据,以 Serial_Num 为键。

但是csv中的数据是顺序的,顺序很重要。

对于每个Serial_Num,有什么方法可以按照它们在 CSV 中的顺序输出坐标列表?

编辑:我现在正在研究 Pandas,因为它有一个 groupBy 方法可能会有所帮助。

【问题讨论】:

    标签: python python-3.x pandas csv dataframe


    【解决方案1】:

    这是一种方式。下面对每个步骤进行细分。

    import pandas as pd
    
    df = pd.read_csv('file.csv', delim_whitespace=True)
    df['GPS'] = list(zip(df.Latitude, df.Longitude))
    df.groupby('Serial_Num')['GPS'].apply(list).to_dict()
    

    读取数据

    df = pd.read_csv('file.csv', delim_whitespace=True)
    
    #        Serial_Num  Latitude  Longitude
    # 0   1950004S11059     -11.1       59.1
    # 1   1950004S11059     -11.6       57.8
    # 2   1950004S11059     -12.4       56.0
    # 3   1950004S11059     -13.2       54.6
    # 4   1950004S11059     -13.8       53.8
    # 5   1950004S11059     -14.8       52.7
    

    制作元组列

    df['GPS'] = list(zip(df.Latitude, df.Longitude))
    
    #        Serial_Num  Latitude  Longitude             GPS
    # 0   1950004S11059     -11.1       59.1   (-11.1, 59.1)
    # 1   1950004S11059     -11.6       57.8   (-11.6, 57.8)
    # 2   1950004S11059     -12.4       56.0   (-12.4, 56.0)
    # 3   1950004S11059     -13.2       54.6   (-13.2, 54.6)
    # 4   1950004S11059     -13.8       53.8   (-13.8, 53.8)
    # 5   1950004S11059     -14.8       52.7   (-14.8, 52.7)
    

    创建字典

    df.groupby('Serial_Num')['GPS'].apply(list).to_dict()
    
    # {'1950004S11059': [(-11.1, 59.100000000000001),
    #                    (-11.6, 57.799999999999997),
    #                    (-12.4, 56.0),
    #                    (-13.199999999999999, 54.600000000000001),
    #                    (-13.800000000000001, 53.799999999999997),
    #                    (-14.800000000000001, 52.700000000000003),
    #                    (-15.9, 52.0),
    #                    (-18.300000000000001, 52.399999999999999),
    #                    (-20.0, 54.0),
    #                    (-22.100000000000001, 55.899999999999999),
    #                    (-26.199999999999999, 59.799999999999997)],
    #  '1950012S14150': [(-14.0, 146.90000000000001),
    #                    (-14.4, 145.80000000000001),
    #                    (-14.9, 145.40000000000001),
    #                    (-15.800000000000001, 145.59999999999999),
    #                    (-18.899999999999999, 149.09999999999999),
    #                    (-22.300000000000001, 152.5)],
    #  '1950013S14139': [(-16.0, 139.0), (-16.300000000000001, 139.0)]}
    

    【讨论】:

    • 是的!! 太棒了。我对 Pandas 非常陌生,但看起来 df.Latitude 中的 Latitude 不是 Pandas 中的设置方法/单词,而是文件中的文字标题,是吗?所以如果我在“状态”下也有状态,我可以做zip(df.State,df.Latitude,df.Longitude),是吗?这三行中发生了很多事情,我必须学习,但是很棒的帖子/答案,谢谢!
    • @pylang - 当我尝试使用 .csv 时,我收到此错误:pandas.errors.ParserError: Error tokenizing data. C error: Expected 5 fields in line 901, saw 6
    • @BruceWayne,您的 csv 文件似乎有问题。您可以在文本编辑器中打开并查看第 901 行中的内容吗?它可能是不应该出现的逗号,或类似的东西。有一种方法可以忽略 pandas [error_bad_lines=False] 的坏行,但这意味着您的数据可能不完整。
    • 我也是这么想的——但是看着它,似乎没有错误的逗号,对吧? See screen shot
    • 我要做的就是将该行粘贴到一个单独的文件中,将其读入 pandas 中,看看它会给你什么。
    【解决方案2】:

    给定

    一个名为foo.csv的文件:

    Serial_Num     Latitude Longitude
    1950004S11059   -11.1   59.1
    1950004S11059   -11.6   57.8
    1950004S11059   -12.4   56
    1950004S11059   -13.2   54.6
    1950004S11059   -13.8   53.8
    1950004S11059   -14.8   52.7
    1950004S11059   -15.9   52
    1950004S11059   -18.3   52.4
    1950004S11059   -20     54
    1950004S11059   -22.1   55.9
    1950004S11059   -26.2   59.8
    1950012S14150   -14     146.9
    1950012S14150   -14.4   145.8
    1950012S14150   -14.9   145.4
    1950012S14150   -15.8   145.6
    1950012S14150   -18.9   149.1
    1950012S14150   -22.3   152.5
    1950013S14139   -16     139
    1950013S14139   -16.3   139
    

    还有一些代码将数据解析为(序列,坐标)的元组:

    import csv
    import collections as ct
    
    
    def read_file(fname):
        with open(fname) as f:
            reader = csv.reader(f)
            next(reader)
            for line in reader:
                #line = [x for x in line[0].split(" ") if x]
                yield line[0], tuple(map(float, line[1:]))
    

    代码

    我们构建了defaultdicts的嵌套:

    data = ct.defaultdict(dict)
    for serial, coords in (read_file("foo.csv")):
        if serial not in data:
            dd = ct.defaultdict(list)
        dd["GPS"].append(coords)
        data[serial] = dd
    
    dict(data)
    

    输出

    {'1950004S11059': defaultdict(list,
                 {'GPS': [
                   (-11.1, 59.1),
                   (-11.6, 57.8),
                   (-12.4, 56.0),
                   (-13.2, 54.6),
                   (-13.8, 53.8),
                   (-14.8, 52.7),
                   (-15.9, 52.0),
                   (-18.3, 52.4),
                   (-20.0, 54.0),
                   (-22.1, 55.9),
                   (-26.2, 59.8)]}),
     '1950012S14150': defaultdict(list,
                 {'GPS': [
                   (-14.0, 146.9),
                   (-14.4, 145.8),
                   (-14.9, 145.4),
                   (-15.8, 145.6),
                   (-18.9, 149.1),
                   (-22.3, 152.5)]}),
     '1950013S14139': defaultdict(list, 
                 {'GPS': [
                   (-16.0, 139.0), 
                   (-16.3, 139.0)]})}
    

    【讨论】:

    • 我用我的.csv(而不是.txt)进行了尝试,它成功地为每个唯一的 Serial_Num 添加了一个条目,但它为每个键返回了空值。 2017161N13119 defaultdict(<class 'list'>, {'GPS': [(), (), (), (), (), (), (), (), (), (), (), (), (), ()]})
    • 我将文件扩展名替换为.csv,它对我有用。尝试将文件重命名为.txt。我怀疑您的 csv 没有正确分隔列。
    • 我在您的评论中看到了不同的序列号。尝试使用我首先发布的数据确认此代码是否有效。 Lmk 会发生什么。
    • 同样的事情 - 我把你的数据放在一个 CSV 中,得到相同的空值。 FWIW,看起来它正确地获取了 GPS 组,只是没有在列表中添加值。您的信息返回:defaultdict(<class 'dict'>, {'1950004S11059': defaultdict(<class 'list'>, {'GPS': [(), (), (), (), (), (), (), (), (), (), ()]}), '1950012S14150': defaultdict(<class 'list'>, {'GPS': [(), (), (), (), (), ()]}), '1950013S14139': defaultdict(<class 'list'>, {'GPS': [(), ()]})})
    • 您尝试将其作为.txt 文件吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-12-29
    • 1970-01-01
    • 1970-01-01
    • 2012-12-14
    • 1970-01-01
    • 2016-08-03
    • 1970-01-01
    相关资源
    最近更新 更多