【问题标题】:Selecting multiple columns in a Pandas dataframe在 Pandas 数据框中选择多列
【发布时间】:2012-07-02 09:23:54
【问题描述】:

我在不同的列中有数据,但我不知道如何提取它以将其保存在另一个变量中。

index  a   b   c
1      2   3   4
2      3   4   5

如何选择'a''b'并将其保存到df1?

我试过了

df1 = df['a':'b']
df1 = df.ix[:, 'a':'b']

似乎都不起作用。

【问题讨论】:

  • 你永远不想使用.ix,因为它是模棱两可的。如果必须,请使用.iloc.loc
  • 有没有一种方法可以在不参考标题名称的情况下完成?就像在 R 中一样,我可以这样做:> csvtable_imp_1 <- csvtable_imp[0:6] 并选择 0 到 6 之间的第一列的增量量。我所要做的就是读取用 readr lib 分隔的 csv 表。跨度>
  • 我用它做了更多的工作。找到了可以按要求工作的东西。默认是选择字符数而不是列数。 infile_1 = largefile_stay.ix[:,0:6]
  • 对于那些迟到的人,ix 现在已被弃用。 Pandas 建议使用:loc(基于标签的索引)或iloc(基于位置的索引)。

标签: python pandas dataframe select


【解决方案1】:

要排除某些列,您可以在列索引中drop 它们。例如:

   A   B    C     D
0  1  10  100  1000
1  2  20  200  2000

选择除两个之外的所有:

df[df.columns.drop(['B', 'D'])]

输出:

   A    C
0  1  100
1  2  200

您也可以使用truncate的方法来选择中间的列:

df.truncate(before='B', after='C', axis=1)

输出:

    B    C
0  10  100
1  20  200

【讨论】:

    【解决方案2】:

    无法按照您尝试的方式对列名(字符串)进行切片。

    这里有几个选项。如果您从上下文中知道要切出哪些变量,则可以通过将列表传递给__getitem__ syntax([])来仅返回这些列的视图。

    df1 = df[['a', 'b']]
    

    或者,如果重要的是用数字而不是它们的名称来索引它们(比如你的代码应该在不知道前两列的名称的情况下自动执行此操作),那么你可以这样做:

    df1 = df.iloc[:, 0:2] # Remember that Python does not slice inclusive of the ending index.
    

    此外,您应该熟悉 Pandas 对象的视图与该对象的副本的概念。上述第一个方法将在内存中返回所需子对象(所需切片)的新副本。

    但有时,Pandas 中的索引约定不这样做,而是为您提供一个新变量,该变量仅引用与原始对象中的子对象或切片相同的内存块。第二种索引方式会发生这种情况,因此您可以使用.copy() 方法对其进行修改以获取常规副本。发生这种情况时,更改您认为的切片对象有时会改变原始对象。留意这一点总是好的。

    df1 = df.iloc[0, 0:2].copy() # To avoid the case where changing df1 also changes df
    

    要使用iloc,您需要知道列位置(或索引)。由于列位置可能会发生变化,您可以使用iloc 和数据框对象的columns 方法的get_loc 函数来获取列索引,而不是硬编码索引。

    {df.columns.get_loc(c): c for idx, c in enumerate(df.columns)}
    

    现在您可以使用此字典通过名称和iloc 访问列。

    【讨论】:

    • 注意:df[['a','b']] 生成一个副本
    • 是的,这在我的回答中是隐含的。如果您出于任何原因更喜欢使用ix[],则有关副本的部分仅供使用ix[]
    • ix 接受切片参数,因此您也可以获取列。例如,df.ix[0:2, 0:2] 获取左上角的 2x2 子数组,就像它对 NumPy 矩阵所做的一样(当然取决于您的列名)。您甚至可以对列的字符串名称使用切片语法,例如df.ix[0, 'Col1':'Col5']。这使得所有在df.columns 数组中恰好在Col1Col5 之间排序的列。说ix 索引行是不正确的。这只是它最基本的用途。它还支持比这更多的索引。所以,ix 非常适合这个问题。
    • @AndrewCassidy 再也不要使用 .ix。如果你想用整数切片,请使用.iloc,它不包括最后一个位置,就像 Python 列表一样。
    • @dte324 如果您的 DataFrame 名为 df,则使用 df.iloc[:, [1, 4]]。通常,如果您想要这种类型的访问模式,您已经知道这些特定的列名,您可以使用 df.loc[:, ['name2', 'name5']] 其中'name2''name5' 是您想要的相应列的列字符串名称,或者查看名字与例如name2 = df.columns[1].
    【解决方案3】:
    def get_slize(dataframe, start_row, end_row, start_col, end_col):
        assert len(dataframe) > end_row and start_row >= 0
        assert len(dataframe.columns) > end_col and start_col >= 0
        list_of_indexes = list(dataframe.columns)[start_col:end_col]
        ans = dataframe.iloc[start_row:end_row][list_of_indexes]
        return ans
    

    只要使用这个功能

    【讨论】:

      【解决方案4】:

      尝试使用pandas.DataFrame.get(见the documentation):

      import pandas as pd
      import numpy as np
      
      dates = pd.date_range('20200102', periods=6)
      df = pd.DataFrame(np.random.randn(6, 4), index=dates, columns=list('ABCD'))
      df.get(['A', 'C'])
      

      【讨论】:

        【解决方案5】:
        df[['a', 'b']]  # Select all rows of 'a' and 'b'column 
        df.loc[0:10, ['a', 'b']]  # Index 0 to 10 select column 'a' and 'b'
        df.loc[0:10, 'a':'b']  # Index 0 to 10 select column 'a' to 'b'
        df.iloc[0:10, 3:5]  # Index 0 to 10 and column 3 to 5
        df.iloc[3, 3:5]  # Index 3 of column 3 to 5
        

        【讨论】:

        • 第三行应该有df.loc[0:10, 'a':'b']。我刚刚编辑了它。
        【解决方案6】:

        您可以使用pandas.DataFrame.filter 方法来过滤或重新排序列,如下所示:

        df1 = df.filter(['a', 'b'])
        

        这在链接方法时也非常有用。

        【讨论】:

        • filter 很棒,但并没有应有的知名度。特别是,您还可以像这样使用正则表达式:df.filter(regex='a|b')。我有一个更长的例子来回答这个问题:stackoverflow.com/questions/29241836/…
        • 过滤器还能够忽略“items= .. list”中不存在的列,这有时非常有用!
        • 这是最好的答案
        【解决方案7】:

        我已经看到了几个答案,但我仍然不清楚。您将如何选择那些感兴趣的列?

        答案是,如果您将它们收集在一个列表中,您可以使用该列表引用这些列。

        示例

        print(extracted_features.shape)
        print(extracted_features)
        
        (63,)
        ['f000004' 'f000005' 'f000006' 'f000014' 'f000039' 'f000040' 'f000043'
         'f000047' 'f000048' 'f000049' 'f000050' 'f000051' 'f000052' 'f000053'
         'f000054' 'f000055' 'f000056' 'f000057' 'f000058' 'f000059' 'f000060'
         'f000061' 'f000062' 'f000063' 'f000064' 'f000065' 'f000066' 'f000067'
         'f000068' 'f000069' 'f000070' 'f000071' 'f000072' 'f000073' 'f000074'
         'f000075' 'f000076' 'f000077' 'f000078' 'f000079' 'f000080' 'f000081'
         'f000082' 'f000083' 'f000084' 'f000085' 'f000086' 'f000087' 'f000088'
         'f000089' 'f000090' 'f000091' 'f000092' 'f000093' 'f000094' 'f000095'
         'f000096' 'f000097' 'f000098' 'f000099' 'f000100' 'f000101' 'f000103']
        

        我有以下列表/NumPy 数组extracted_features,指定 63 列。原始数据集有 103 列,我想准确提取那些,然后我会使用

        dataset[extracted_features]
        

        你最终会得到这个

        这是您在machine learning 中经常使用的东西(更具体地说,在功能选择中)。我也想讨论其他方式,但我认为其他 Stack Overflower 用户已经涵盖了这一点。

        【讨论】:

          【解决方案8】:

          您可以使用 Pandas。

          我创建了 DataFrame:

          import pandas as pd
          df = pd.DataFrame([[1, 2,5], [5,4, 5], [7,7, 8], [7,6,9]],
                            index=['Jane', 'Peter','Alex','Ann'],
                            columns=['Test_1', 'Test_2', 'Test_3'])
          

          数据框:

                 Test_1  Test_2  Test_3
          Jane        1       2       5
          Peter       5       4       5
          Alex        7       7       8
          Ann         7       6       9
          

          按名称选择一列或多列:

          df[['Test_1', 'Test_3']]
          
                 Test_1  Test_3
          Jane        1       5
          Peter       5       5
          Alex        7       8
          Ann         7       9
          

          你也可以使用:

          df.Test_2
          

          你会得到Test_2的专栏:

          Jane     2
          Peter    4
          Alex     7
          Ann      6
          

          您还可以使用 .loc() 从这些行中选择列和行。这称为“切片”。请注意,我从列 Test_1Test_3

          df.loc[:, 'Test_1':'Test_3']
          

          “切片”是:

                 Test_1  Test_2  Test_3
          Jane        1       2       5
          Peter       5       4       5
          Alex        7       7       8
          Ann         7       6       9
          

          如果您只想要Test_1Test_3 列中的PeterAnn

          df.loc[['Peter', 'Ann'], ['Test_1', 'Test_3']]
          

          你得到:

                 Test_1  Test_3
          Peter       5       5
          Ann         7       9
          

          【讨论】:

            【解决方案9】:

            你也可以使用df.pop():

            >>> df = pd.DataFrame([('falcon', 'bird',    389.0),
            ...                    ('parrot', 'bird',     24.0),
            ...                    ('lion',   'mammal',   80.5),
            ...                    ('monkey', 'mammal', np.nan)],
            ...                   columns=('name', 'class', 'max_speed'))
            >>> df
                 name   class  max_speed
            0  falcon    bird      389.0
            1  parrot    bird       24.0
            2    lion  mammal       80.5
            3  monkey  mammal
            
            >>> df.pop('class')
            0      bird
            1      bird
            2    mammal
            3    mammal
            Name: class, dtype: object
            
            >>> df
                 name  max_speed
            0  falcon      389.0
            1  parrot       24.0
            2    lion       80.5
            3  monkey        NaN
            

            请使用df.pop(c)

            【讨论】:

              【解决方案10】:

              与熊猫,

              知道列名

              dataframe[['column1','column2']]
              

              通过 iloc 和具有索引号的特定列进行选择:

              dataframe.iloc[:,[1,2]]
              

              with loc 列名可以像这样使用

              dataframe.loc[:,['column1','column2']]
              

              【讨论】:

                【解决方案11】:

                另一种简单的方法:迭代行

                使用iterows

                 df1 = pd.DataFrame() # Creating an empty dataframe
                 for index,i in df.iterrows():
                    df1.loc[index, 'A'] = df.loc[index, 'A']
                    df1.loc[index, 'B'] = df.loc[index, 'B']
                    df1.head()
                

                【讨论】:

                • Please do not recommend the use of iterrows(). 它是 pandas 历史上最糟糕的反模式的公然推动者。
                • 你能解释一下“最坏的反模式”是什么意思吗?
                • 恕我直言,iterrows() 应该是使用 pandas 时的最后一个选项。
                【解决方案12】:

                从 0.21.0 开始,将 .loc[] 与一个或多个缺少标签的列表一起使用已弃用,取而代之的是 .reindex。所以,你的问题的答案是:

                df1 = df.reindex(columns=['b','c'])
                

                在以前的版本中,只要找到至少一个键,使用.loc[list-of-labels] 就可以工作(否则会引发KeyError)。此行为已弃用,现在显示警告消息。推荐的替代方法是使用.reindex()

                Indexing and Selecting Data了解更多信息。

                【讨论】:

                  【解决方案13】:

                  前面的答案中讨论的不同方法基于以下假设:用户知道要删除或子集的列索引,或者用户希望使用一系列列(例如在 'C' 之间)对数据帧进行子集化: 'E')。

                  pandas.DataFrame.drop() 当然是根据用户定义的列列表对数据进行子集化的一种选择(尽管您必须小心,始终使用数据框的副本和 inplace 参数不应设置为 True!!)

                  另一个选项是使用 pandas.columns.difference(),它对列名进行设置差异,并返回包含所需列的数组的索引类型。以下是解决方案:

                  df = pd.DataFrame([[2,3,4], [3,4,5]], columns=['a','b','c'], index=[1,2])
                  columns_for_differencing = ['a']
                  df1 = df.copy()[df.columns.difference(columns_for_differencing)]
                  print(df1)
                  

                  输出将是:

                      b   c
                  1   3   4
                  2   4   5
                  

                  【讨论】:

                  • copy() 不是必需的。即:df1 = df[df.columns.difference(columns_for_differencing)] 将返回一个新的/复制的数据帧。您将能够修改df1 而无需更改df。谢谢你,顺便说一句。这正是我所需要的。
                  【解决方案14】:

                  如果你想通过行索引和列名获取一个元素,你可以像df['b'][0]那样做。它就像您想象的一样简单。

                  或者您可以使用df.ix[0,'b'] - 混合使用索引和标签。

                  注意:自 v0.20 起,ix 已被弃用,取而代之的是 loc / iloc

                  【讨论】:

                    【解决方案15】:

                    我发现这个方法非常有用:

                    # iloc[row slicing, column slicing]
                    surveys_df.iloc [0:3, 1:4]
                    

                    更多详情请见here

                    【讨论】:

                    • 你会怎么看,比如说,只有第 2 列和第 5 列?
                    • 那就是surveys_df.iloc [:, [2,5]]
                    【解决方案16】:

                    从 0.11.0 版开始,列可以按照您尝试使用 .loc 索引器的方式进行切片:

                    df.loc[:, 'C':'E']
                    

                    等价于

                    df[['C', 'D', 'E']]  # or df.loc[:, ['C', 'D', 'E']]
                    

                    并返回列CE


                    随机生成的 DataFrame 的演示:

                    import pandas as pd
                    import numpy as np
                    np.random.seed(5)
                    df = pd.DataFrame(np.random.randint(100, size=(100, 6)),
                                      columns=list('ABCDEF'),
                                      index=['R{}'.format(i) for i in range(100)])
                    df.head()
                    
                    Out:
                         A   B   C   D   E   F
                    R0  99  78  61  16  73   8
                    R1  62  27  30  80   7  76
                    R2  15  53  80  27  44  77
                    R3  75  65  47  30  84  86
                    R4  18   9  41  62   1  82
                    

                    要获取从 C 到 E 的列(请注意,与整数切片不同,列中包含“E”):

                    df.loc[:, 'C':'E']
                    
                    Out:
                          C   D   E
                    R0   61  16  73
                    R1   30  80   7
                    R2   80  27  44
                    R3   47  30  84
                    R4   41  62   1
                    R5    5  58   0
                    ...
                    

                    根据标签选择行也是如此。从这些列中获取行 'R6' 到 'R10':

                    df.loc['R6':'R10', 'C':'E']
                    
                    Out:
                          C   D   E
                    R6   51  27  31
                    R7   83  19  18
                    R8   11  67  65
                    R9   78  27  29
                    R10   7  16  94
                    

                    .loc 也接受布尔数组,因此您可以选择数组中对应条目为True 的列。例如,df.columns.isin(list('BCD')) 返回 array([False, True, True, True, False, False], dtype=bool) - 如果列名在列表中,则为 True ['B', 'C', 'D'];否则为假。

                    df.loc[:, df.columns.isin(list('BCD'))]
                    
                    Out:
                          B   C   D
                    R0   78  61  16
                    R1   27  30  80
                    R2   53  80  27
                    R3   65  47  30
                    R4    9  41  62
                    R5   78   5  58
                    ...
                    

                    【讨论】:

                    • df.loc[:, 'C':'E'] 这是我正在寻找的确切答案。我将 C 和 E 放在另一个括号中,这是我的错误。谢谢
                    【解决方案17】:

                    在最新版本的 Pandas 中,有一个简单的方法可以做到这一点。列名(字符串)可以以您喜欢的任何方式进行切片。

                    columns = ['b', 'c']
                    df1 = pd.DataFrame(df, columns=columns)
                    

                    【讨论】:

                    • 这只能在创建时完成。问题是询问您是否已经在数据框中拥有它。
                    • df1 = df.iloc[:, columns] 在您已经拥有数据框时有效。
                    • 而且这个创建列名的创建界面一直都有。
                    • @BálintSass 如果您已经知道列名,而不仅仅是它们的整数位置(索引)。
                    【解决方案18】:

                    假设你的列名(df.columns)是['index','a','b','c'],那么你想要的数据在 第三列和第四列。如果你在脚本运行时不知道他们的名字,你可以这样做

                    newdf = df[df.columns[2:4]] # Remember, Python is zero-offset! The "third" entry is at slot two.
                    

                    正如 EMS 在 his answer 中指出的那样,df.ix 对列的切片更简洁一些,但 .columns 切片接口可能更自然,因为它使用普通的一维 Python 列表索引/切片语法。

                    警告'index'DataFrame 列的错误名称。相同的标签也用于真正的df.index 属性,即Index 数组。所以你的列由df['index']返回,真正的DataFrame索引由df.index返回。 Index 是一种特殊的 Series,针对其元素值的查找进行了优化。对于 df.index,它用于按标签查找行。 df.columns 属性也是一个 pd.Index 数组,用于通过标签查找列。

                    【讨论】:

                    • 正如我在上面的评论中所指出的,.ix 仅用于行。用于通用切片,可用于多维切片。它基本上只是 NumPy 通常的__getitem__ 语法的一个接口。也就是说,只需应用转置操作df.T,您就可以轻松地将列切片问题转换为行切片问题。您的示例使用columns[1:3],这有点误导。 columns 的结果是 Series;注意不要把它当作一个数组来对待。此外,您可能应该将其更改为 columns[2:3] 以匹配您的“3rd & 4th”评论。
                    • @Mr.F:我的[2:4] 是正确的。你的[2:3] 是错误的。并且使用标准 python 切片符号生成序列/系列不会误导 IMO。但我喜欢你绕过 DataFrame 接口来使用 ix 访问底层 numpy 数组。
                    • 在这种情况下你是对的,但我想说的是一般来说,slicing with labels in Pandas is inclusive of the slice endpoint(或者至少这是大多数以前的 Pandas 版本中的行为)。因此,如果您检索df.columns 并希望按标签 对其进行切片,那么与您按整数索引位置 对其进行切片时,您将拥有不同的切片语义。不过,我在之前的评论中肯定没有很好地解释它。
                    • 啊,现在我明白你的意思了。我忘记了 columns 是一个不可变的系列,并且 getter 已被覆盖以使用标签作为索引。感谢您花时间澄清。
                    • 请注意弃用警告:.ix 已弃用。因此这是有道理的:newdf = df[df.columns[2:4]]
                    【解决方案19】:

                    要选择多个列,提取并在之后查看它们:df 以前命名为数据框,然后创建新的数据框 df1,然后选择要提取和查看的列 A 到 D。

                    df1 = pd.DataFrame(data_frame, columns=['Column A', 'Column B', 'Column C', 'Column D'])
                    df1
                    

                    所有必填列都会显示出来!

                    【讨论】:

                      【解决方案20】:

                      您可以使用 Pandas DataFrame 上的 drop() 函数提供要删除的列列表并返回 DataFrame,其中仅包含所需的列。

                      只是说说

                      colsToDrop = ['a']
                      df.drop(colsToDrop, axis=1)
                      

                      将返回仅包含 bc 列的 DataFrame。

                      drop 方法记录在 here

                      【讨论】:

                        【解决方案21】:
                        In [39]: df
                        Out[39]: 
                           index  a  b  c
                        0      1  2  3  4
                        1      2  3  4  5
                        
                        In [40]: df1 = df[['b', 'c']]
                        
                        In [41]: df1
                        Out[41]: 
                           b  c
                        0  3  4
                        1  4  5
                        

                        【讨论】:

                        • 如果我想重命名列,例如:df[['b as foo', 'c as bar'] 这样输出将列 b 重命名为 foo 并将列 c 重命名为 bar跨度>
                        • df[['b', 'c']].rename(columns = {'b' : 'foo', 'c' : 'bar'})
                        • 解释一下。例如,要点是什么?您可以edit your answer - 无需“编辑:”、“更新:”或类似内容 - 答案应该看起来就像是今天写的一样。
                        猜你喜欢
                        • 1970-01-01
                        • 2021-07-08
                        • 1970-01-01
                        • 2021-11-10
                        • 1970-01-01
                        相关资源
                        最近更新 更多