【问题标题】:How to create a DataFrame while preserving order of the columns?如何在保留列顺序的同时创建 DataFrame?
【发布时间】:2016-04-11 03:32:58
【问题描述】:

如何从多个 numpy 数组、Pandas 系列或 Pandas DataFrame 中创建一个 DataFrame,同时保留列的顺序?

例如,我有这两个numpy 数组,我想将它们组合成一个Pandas DataFrame。

foo = np.array( [ 1, 2, 3 ] )
bar = np.array( [ 4, 5, 6 ] )

如果我这样做,bar 列将排在第一位,因为dict 不保留顺序。

pd.DataFrame( { 'foo': pd.Series(foo), 'bar': pd.Series(bar) } )

    bar foo
0   4   1
1   5   2
2   6   3

我可以这样做,但是当我需要组合许多变量时会变得乏味。

pd.DataFrame( { 'foo': pd.Series(foo), 'bar': pd.Series(bar) }, columns = [ 'foo', 'bar' ] )

编辑:有没有办法在一个操作中指定要连接的变量并组织列顺序?也就是说,我不介意使用多行来完成整个操作,但我宁愿不必指定要多次连接的变量(因为我将大量更改代码,这很容易出错) .

EDIT2:还有一点。如果我想添加或删除要加入的变量之一,我只想在一个地方添加/删除。

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    原解决方法:collections.OrderedDict 使用不正确

    在我最初的解决方案中,我建议使用python标准库中collections包中的OrderedDict

    >>> import numpy as np
    >>> import pandas as pd
    >>> from collections import OrderedDict
    >>>
    >>> foo = np.array( [ 1, 2, 3 ] )
    >>> bar = np.array( [ 4, 5, 6 ] )
    >>>
    >>> pd.DataFrame( OrderedDict( { 'foo': pd.Series(foo), 'bar': pd.Series(bar) } ) )
    
       foo  bar
    0    1    4
    1    2    5
    2    3    6
    

    正确的解决方案:传递键值元组对来保存订单

    但是,如前所述,如果将普通字典传递给OrderedDict,则可能仍无法保留顺序,因为在构建字典时顺序是随机的。但是,一种解决方法是将键值元组对列表转换为OrderedDict,正如this SO post 所建议的那样:

    >>> import numpy as np
    >>> import pandas as pd
    >>> from collections import OrderedDict
    >>>
    >>> a = np.array( [ 1, 2, 3 ] )
    >>> b = np.array( [ 4, 5, 6 ] )
    >>> c = np.array( [ 7, 8, 9 ] )
    >>>
    >>> pd.DataFrame( OrderedDict( { 'a': pd.Series(a), 'b': pd.Series(b), 'c': pd.Series(c) } ) )
    
       a  c  b
    0  1  7  4
    1  2  8  5
    2  3  9  6
    
    >>> pd.DataFrame( OrderedDict( (('a', pd.Series(a)), ('b', pd.Series(b)), ('c', pd.Series(c))) ) )
    
       a  b  c
    0  1  4  7
    1  2  5  8
    2  3  6  9
    

    【讨论】:

    • 如果您只是将普通字典传递给OrderedDict,您仍然会丢失订单,一旦您创建普通字典,它就会丢失
    • @ceilingcat 我已经编辑了我的答案。为了确保OrderedDict 保留您的订单,我建议使用键值对元组进行构建。希望有帮助!
    【解决方案2】:

    在创建DataFrame 时使用columns 关键字:

    pd.DataFrame({'foo': foo, 'bar': bar}, columns=['foo', 'bar'])
    

    另外,请注意您不需要创建系列。

    【讨论】:

    • 我最喜欢这个解决方案。
    • 这是最好的解决方案。少麻烦!
    【解决方案3】:

    要保留列顺序,请将您的 numpy 数组作为元组列表传递给DataFrame.from_items

    >>> df = pd.DataFrame.from_items([('foo', foo), ('bar', bar)])
    
       foo  bar
    0    1    4
    1    2    5
    2    3    6
    

    更新

    从 pandas 0.23 开始,from_items 已弃用并将被删除。所以使用from_dict 传递numpy 数组。要使用from_dict,您需要将项目作为字典传递:

    >>> from collections import OrderedDict as OrderedDict
    >>> df = pd.DataFrame.from_dict(OrderedDict(zip(['foo', 'bar'], [foo, bar])))
    

    从 python 3.7 开始,您可以依赖保留的插入顺序(请参阅https://mail.python.org/pipermail/python-dev/2017-December/151283.html),因此:

    >>> df = pd.DataFrame.from_dict(dict(zip(['foo', 'bar'], [foo, bar])))
    

    或者简单地说:

    >>> df = pd.DataFrame(dict(zip(['foo', 'bar'], [foo, bar])))
    

    【讨论】:

    • 这很好用,但给了我一个弃用警告:FutureWarning: from_items is deprecated. Please use DataFrame.from_dict(dict(items), ...) instead. DataFrame.from_dict(OrderedDict(items)) may be used to preserve the key order.
    • @kabdulla 感谢您发现弃用。我已经更新了答案。再次感谢。
    【解决方案4】:

    创建数据框后,您可以简单地使用您想要的方式重新排序列

    df= df[['foo','bar']]
    

    【讨论】:

      【解决方案5】:

      我无法评论询问,但是您将如何首先指定列的顺序(因为您不能使用常规字典)?

      如果你想维护一个有序的字典:

      from collections import OrderedDict
      import numpy as np
      import pandas as pd
      
      data = OrderedDict()
      data['foo'] = np.array([1, 2, 3])
      data['bar'] = np.array([4, 5, 6])
      
      df = pd.DataFrame(data)
      

      如果您只有一个订单键列表:

      data = {key: value for key, value in data.iteritems()}
      df = pd.concat(data.values(), keys=['foo', 'bar'], axis=1)
      

      @tfv 的回答可能是做你想做的最简洁的方式。

      【讨论】:

      • 你的第一个答案对我有用(我不认为第二个有用)。澄清一下,如果我需要添加/删除一列,我不想在多个地方都这样做,因为它容易出错。
      【解决方案6】:
      >>> pd.concat([pd.Series(eval(col), name=col) for col in ['foo', 'bar']], axis=1)
         foo  bar
      0    1    4
      1    2    5
      2    3    6
      

      这可以使用eval。您的列名列表必须与相应的变量名匹配。

      >>> eval('foo')
      array([1, 2, 3])
      

      【讨论】:

        【解决方案7】:

        这可能是另一种处理方式:

        foo = np.array( [ 1, 2, 3 ] )
        bar = np.array( [ 4, 5, 6 ] )
        stacked = np.vstack((x,y)).T
        stacked
        array([[1, 4],
               [2, 5],
               [3, 6]])
        
        new_df = pd.DataFrame(stacked, columns = ['foo', 'bar'] )
        new_df
           foo  bar
        0   1   4
        1   2   5
        2   3   6
        

        【讨论】:

          【解决方案8】:

          只包含数据的数据框,然后转置它。

          然后添加列。

          >>> foo = np.array( [ 1, 2, 3 ] )
          >>> bar = np.array( [ 4, 5, 6 ] )
          >>>     
          >>> df = pd.DataFrame([foo, bar]).T
          >>> df.columns = ['foo','bar']
          >>> df
          
            foo bar
          0  1   4
          1  2   5
          2  3   6
          

          【讨论】:

            【解决方案9】:

            另一个粗略的解决方案可能是将 X_ 传递给列的标题,其中 X 是列的顺序号:

            pd.DataFrame( { '2_foo': pd.Series(foo), '1_bar': pd.Series(bar) } )
            

            之后,您可以使用列或其他东西再次重命名列! 世界上更少的pythonic代码!!!

            祝朋友们好运!

            【讨论】:

              【解决方案10】:

              我的做法如下:

              # Creating list of dict
              list_of_dicts = ({'key1':'valueA', 'key2':'valueB},{'key1':'valueC', 'key2':'valueD}')
              
              #getting list of keys from the dict
              keys_list = list(list_of_dicts.keys())
              
              # and finally
              df = pd.DataFrame(list_of_dicts, columns = keys_list)
              

              非常适合我。

              【讨论】:

                【解决方案11】:

                这个问题很老了,但希望为“在将 csv 文件读入 pandas 数据框时保留列的顺序”的问题提供我的解决方案:

                import numpy as np
                import pandas as pd
                
                # Get column count as a list
                cols = np.arange(0, hmprice.shape[1])
                df = pd.read_csv('train.csv', usecols=cols)
                df.head()
                

                Default Order of dataframe:
                Preserved order of dataframe:

                注意:属性 usecols 可以采用列名或列索引;但熊猫不尊重列名或列索引的“任何其他顺序”。

                例如,

                    df = pd.read_csv('train.csv', usecols=[1, 2, 3])<br/>
                or
                    df = pd.read_csv('train.csv', usecols=[3, 2, 1])<br/>
                

                给出相同的结果。

                【讨论】:

                  猜你喜欢
                  • 2013-03-17
                  • 2016-09-25
                  • 1970-01-01
                  • 2021-01-23
                  • 1970-01-01
                  • 1970-01-01
                  • 2020-12-21
                  • 2018-05-28
                  • 2020-08-19
                  相关资源
                  最近更新 更多