Python:标识由两列给定的路由/路径

Python:标识由两列给定的路由/路径,python,pandas,Python,Pandas,我有一个输入文件(csv文件),其中的数据在列组中有重复条目,在列大小中可能有重复条目 下面给出了一个只包含一组数据的代码段。但是,实际数据文件中有几个组。因此,这只是一个简短的示例(sample.csv): 由于数据来自外部软件,我无法更改任何有关数据格式或数据布局的内容。因此,我需要导入数据以进行进一步的数据处理,并执行以下任务: 每组只保留一个条目。此条目在size列中必须具有最大值 获取穿过组的路径,路径可以从列from和to排列 我决定使用pandas进行数据处理,因为真实的数据文件相

我有一个输入文件(csv文件),其中的数据在列
组中有重复条目,在列
大小中可能有重复条目

下面给出了一个只包含一组数据的代码段。但是,实际数据文件中有几个组。因此,这只是一个简短的示例(
sample.csv
):

由于数据来自外部软件,我无法更改任何有关数据格式或数据布局的内容。因此,我需要导入数据以进行进一步的数据处理,并执行以下任务:

  • 每组只保留一个条目。此条目在
    size
    列中必须具有最大值
  • 获取穿过组的路径,路径可以从列
    from
    to
    排列
  • 我决定使用
    pandas
    进行数据处理,因为真实的数据文件相当复杂,我想拥有它的永久格式化功能。但是,如果有任何其他(更合适的)工具或方法使用其他Python模块,那么这些工具或方法将是完全好的,根本不是问题

    为了完成第一项任务,我做了:

    import pandas as pd
    
    # open file and read data
    with open('sample.csv') as f:
        data = pd.read_csv(f)
    
    # sort descending by columns `group` and `size`
    # sorting descending because `df.drop_duplicates()` keeps first element by default
    df_sorted = data.sort_values(['group', 'size'], ascending=False)
    
    # drop duplicates in order to keep first entry only
    one_entry = df_sorted.drop_duplicates('group')
    
    # print handled data
    print(one_entry)
    
    这将导致所需的输出:

           group  size    from      to
    3  group32a4  1400  ru1u5r  fvvskj
    
    所以,我需要完成第二项任务。由于上述所有数据处理都不是就地完成的,因此我能够在整个数据处理过程中访问所有阶段的数据

    不幸的是,我不知道该怎么做。我对如何做到这一点有一些概念上的想法。 首先,我需要安排出每个组子集的路由。在上述示例中,这将导致:

    rpziz0 --> oxlwtg --> ru1u5r --> fvvskj --> 6sq2gp --> m4qfce --> 60m2eq
    
    之后,我需要提取来源和目的地,并总结如下路线:

    rpziz0 --> 60m2eq
    
    这将导致总体输出:

           group  size    from      to
    3  group32a4  1400  rpziz0  60m2eq
    
    因此,我提出的问题如下:

    我如何从每个
    标签定义的每个子集中识别路由(最好使用熊猫的方法)

    注意:使用Python 3.4.3,Pandas 0.17.1,您可以使用with和last。为了更好的测试,增加了下一组:

    print df
            group  size    from      to
    0   group32a4   500  6sq2gp  m4qfce
    1   group32a4   800  oxlwtg  ru1u5r
    2   group32a4  1200  rpziz0  oxlwtg
    3   group32a4  1400  ru1u5r  fvvskj
    4   group32a4   500  m4qfce  60m2eq
    5   group32a4    50  fvvskj  6sq2gp
    6   group13a4   500  6sq2gp  m4qfce
    7   group13a4   800  oxlwtg  ru1u5r
    8   group13a4  1200  rpziz0  oxlwtg
    9   group13a4  1400  ru1u5r  fvvskj
    10  group13a4   500  m4qfce  60m2eq
    11  group13a4    50  fvvskj  6sq2gp
    
    #set index and stack data - columns 'from' and 'to' to one column 'route'
    df = df.set_index(['group', 'size']).stack().reset_index(name='route')
    
    编辑:

    类似地,我认为使用函数
    f
    和,,,填充数据帧的解决方案更快:

    您可以使用with和last。为了更好的测试,增加了下一组:

    print df
            group  size    from      to
    0   group32a4   500  6sq2gp  m4qfce
    1   group32a4   800  oxlwtg  ru1u5r
    2   group32a4  1200  rpziz0  oxlwtg
    3   group32a4  1400  ru1u5r  fvvskj
    4   group32a4   500  m4qfce  60m2eq
    5   group32a4    50  fvvskj  6sq2gp
    6   group13a4   500  6sq2gp  m4qfce
    7   group13a4   800  oxlwtg  ru1u5r
    8   group13a4  1200  rpziz0  oxlwtg
    9   group13a4  1400  ru1u5r  fvvskj
    10  group13a4   500  m4qfce  60m2eq
    11  group13a4    50  fvvskj  6sq2gp
    
    #set index and stack data - columns 'from' and 'to' to one column 'route'
    df = df.set_index(['group', 'size']).stack().reset_index(name='route')
    
    编辑:

    类似地,我认为使用函数
    f
    和,,,填充数据帧的解决方案更快:


    您导入了
    io
    ,以便从包含示例数据的字符串中获取类似文件的对象。但是,为什么要导入
    numpy
    ?我看不出这有什么用,是吗?可能我遗漏了什么…不需要Nunpy。我编辑了答案,因为它不适用于多个组。您导入了
    io
    ,以便从包含示例数据的字符串中获取类似文件的对象。但是,为什么要导入
    numpy
    ?我看不出这有什么用,是吗?也许我遗漏了什么…不需要修女。我编辑答案,因为它不适用于多个小组。
    print df
            group  size level_2   route
    0   group32a4   500    from  6sq2gp
    1   group32a4   500      to  m4qfce
    2   group32a4   800    from  oxlwtg
    3   group32a4   800      to  ru1u5r
    4   group32a4  1200    from  rpziz0
    5   group32a4  1200      to  oxlwtg
    6   group32a4  1400    from  ru1u5r
    7   group32a4  1400      to  fvvskj
    8   group32a4   500    from  m4qfce
    9   group32a4   500      to  60m2eq
    10  group32a4    50    from  fvvskj
    11  group32a4    50      to  6sq2gp
    12  group13a4   500    from  6sq2gp
    13  group13a4   500      to  m4qfce
    14  group13a4   800    from  oxlwtg
    15  group13a4   800      to  ru1u5r
    16  group13a4  1200    from  rpziz0
    17  group13a4  1200      to  oxlwtg
    18  group13a4  1400    from  ru1u5r
    19  group13a4  1400      to  fvvskj
    20  group13a4   500    from  m4qfce
    21  group13a4   500      to  60m2eq
    22  group13a4    50    from  fvvskj
    23  group13a4    50      to  6sq2gp
    
    def f(x):
        #set column size to max
        x['size'] =  x['size'].max()
        return x.drop_duplicates('route', keep=False)
    
    #apply custom function f
    df = df.groupby('group').apply(f).reset_index(drop=True)
    print df
           group  size level_2   route
    0  group13a4  1400    from  rpziz0
    1  group13a4  1400      to  60m2eq
    2  group32a4  1400    from  rpziz0
    3  group32a4  1400      to  60m2eq
    
    #reshape data, remove column tmp
    df = df.pivot(index='group', columns='level_2').reset_index()
    df.columns = ['group','size','tmp','from', 'to']
    df = df.drop('tmp', axis=1)
    print df
           group  size    from      to
    0  group13a4  1400  rpziz0  60m2eq
    1  group32a4  1400  rpziz0  60m2eq
    
    def f(x):
        #get max of column size
        m = x['size'].max()
        #remove all duplicates - stay only one value from and one value to
        x = x.drop_duplicates('route', keep=False)
        x['group'] = x.iat[0, 0]
        x['size'] = m
        x['from'] = x.iat[0, 3]
        x['to'] = x.iat[1, 3]
    
        #print x
        #return first row and columns group, size from to
        #print x.iloc[0,[0,1,4,5]]
        return  x.iloc[0,[0,1,4,5]]
    
    #apply custom function f
    df = df.groupby('group').apply(f).reset_index(drop=True)
    print df
           group  size    from      to
    0  group13a4  1400  rpziz0  60m2eq
    1  group32a4  1400  rpziz0  60m2eq