【问题标题】:How to take column-slices of dataframe in pandas如何在熊猫中获取数据框的列片
【发布时间】:2012-05-26 19:27:22
【问题描述】:

我从 CSV 文件加载了一些机器学习数据。前 2 列是观测值,其余列是特征。

目前,我执行以下操作:

data = pandas.read_csv('mydata.csv')

这给出了类似的东西:

data = pandas.DataFrame(np.random.rand(10,5), columns = list('abcde'))

我想将此数据帧分割成两个数据帧:一个包含ab 列,另一个包含cde 列。

不可能写出类似的东西

observations = data[:'c']
features = data['c':]

我不确定最好的方法是什么。我需要pd.Panel吗?

顺便说一句,我发现数据帧索引非常不一致:data['a'] 是允许的,但 data[0] 是不允许的。另一方面,data['a':] 是不允许的,但 data[0:] 是允许的。 这有实际原因吗?如果列是由 Int 索引的,这真的很令人困惑,因为 data[0] != data[0:1]

【问题讨论】:

  • 当您执行 df[...] 时,DataFrame 本质上是一个类似 dict 的对象,但是有一些便利,例如df[5:10] 被添加用于选择行 (pandas.pydata.org/pandas-docs/stable/…)
  • 那么这种不一致性是为了方便而做出的设计决定?好的,但对于初学者来说肯定需要更明确!
  • 支持便利性的设计考虑使得学习曲线陡峭。我希望一开始就有更好的文档,只是提供一个一致的界面。例如,只关注ix界面。

标签: python pandas numpy dataframe slice


【解决方案1】:

2017 答案 - pandas 0.20:.ix 已弃用。使用 .loc

deprecation in the docs

.loc 使用基于标签的索引来选择行和列。标签是索引或列的值。使用.loc 切片包括最后一个元素。

假设我们有一个包含以下列的 DataFrame:
foobarquzantcatsatdat

# selects all rows and all columns beginning at 'foo' up to and including 'sat'
df.loc[:, 'foo':'sat']
# foo bar quz ant cat sat

.loc 接受与 Python 列表对行和列所做的相同切片表示法。切片符号为start:stop:step

# slice from 'foo' to 'cat' by every 2nd column
df.loc[:, 'foo':'cat':2]
# foo quz cat

# slice from the beginning to 'bar'
df.loc[:, :'bar']
# foo bar

# slice from 'quz' to the end by 3
df.loc[:, 'quz'::3]
# quz sat

# attempt from 'sat' to 'bar'
df.loc[:, 'sat':'bar']
# no columns returned

# slice from 'sat' to 'bar'
df.loc[:, 'sat':'bar':-1]
sat cat ant quz bar

# slice notation is syntatic sugar for the slice function
# slice from 'quz' to the end by 2 with slice function
df.loc[:, slice('quz',None, 2)]
# quz cat dat

# select specific columns with a list
# select columns foo, bar and dat
df.loc[:, ['foo','bar','dat']]
# foo bar dat

您可以按行和列进行切片。例如,如果您有 5 行标签为 vwxyz

# slice from 'w' to 'y' and 'foo' to 'ant' by 3
df.loc['w':'y', 'foo':'ant':3]
#    foo ant
# w
# x
# y

【讨论】:

  • 如果您将 apply 与 lambda 行一起使用,例如:df['newcol'] = df.apply(lambda row: myfunc(row), axis=1),那么您可以在 myfunc(row){ ... 中使用 row['foo':'ant']。例如(根据this StackOverflow answer),在myfunc 中,您可以评估其中任何一个是否为非数字:row['foo':'ant'].apply(lambda x: isinstance(x, str)).any()
  • .iloc 现在应该使用,而不是 .loc。解决这个问题,我会支持它。
  • @craned - 这是不正确的。来自 Pandas 文档: .loc 主要是基于标签的,但也可以与布尔数组一起使用。 .loc 将在未找到项目时引发 KeyError。关于 .iloc 也有类似的声明,但它专门指的是基于索引的切片。换句话说,在这个例子中,他使用了基于标签的索引,而 .loc 是正确的选择(基本上是唯一的选择)。例如,如果您想按位置 -rows 5:10 进行切片,请使用 .iloc
  • 如果我们想要 ['foo', 'ant', 'cat', 'sat', 'dat'],没有 bar 和 quz,我们可以这样做:[ 'foo', 'ant': 'dat'],最快的方法是什么?
【解决方案2】:

注意: .ix 自 Pandas v0.20 起已被弃用。您应该酌情使用.loc.iloc

DataFrame.ix 索引是您要访问的内容。这有点令人困惑(我同意 Pandas 索引有时令人困惑!),但以下似乎可以满足您的需求:

>>> df = DataFrame(np.random.rand(4,5), columns = list('abcde'))
>>> df.ix[:,'b':]
      b         c         d         e
0  0.418762  0.042369  0.869203  0.972314
1  0.991058  0.510228  0.594784  0.534366
2  0.407472  0.259811  0.396664  0.894202
3  0.726168  0.139531  0.324932  0.906575

其中 .ix[行切片,列切片] 是正在解释的内容。更多关于 Pandas 索引的信息:http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-advanced

【讨论】:

  • 注意 pandas 中的范围包括两个端点,即>>>data.ix[:, 'a':'c'] a b c 0 0.859192 0.881433 0.843624 1 0.744979 0.427986 0.177159
  • 多列 cab 像这样传递df.ix[:,[0,3,4]]
  • @Karmel:上面的输出中看起来像是复制/粘贴错误。也许你的意思是df.ix[:,'b':'e']
  • 最好使用loc而不是ixstackoverflow.com/a/31593712/4323
  • 这样的旧答案需要删除。 .ix 已弃用,不应使用。
【解决方案3】:

让我们以 seaborn 包中的 Titanic 数据集为例

# Load dataset (pip install seaborn)
>> import seaborn.apionly as sns
>> titanic = sns.load_dataset('titanic')

使用列名

>> titanic.loc[:,['sex','age','fare']]

使用列索引

>> titanic.iloc[:,[2,3,6]]

使用 ix(早于 Pandas <.20>

>> titanic.ix[:,[‘sex’,’age’,’fare’]]

>> titanic.ix[:,[2,3,6]]

使用重新索引方法

>> titanic.reindex(columns=['sex','age','fare'])

【讨论】:

  • 在 pandas 0.20 中:.ix 已弃用。
  • 弃用警告:Passing list-likes to .loc or [] with any missing label will raise KeyError in the future, you can use .reindex() as an alternative. 当您使用df.loc[:, some_list_of_columns]
【解决方案4】:

另外,给定一个 DataFrame

数据

如在您的示例中,如果您只想提取列 a 和 d(即第一列和第四列),则可以使用 pandas 数据框中的 iloc 方法,并且可以非常有效地使用。您只需要知道要提取的列的索引。例如:

>>> data.iloc[:,[0,3]]

会给你

          a         d
0  0.883283  0.100975
1  0.614313  0.221731
2  0.438963  0.224361
3  0.466078  0.703347
4  0.955285  0.114033
5  0.268443  0.416996
6  0.613241  0.327548
7  0.370784  0.359159
8  0.692708  0.659410
9  0.806624  0.875476

【讨论】:

    【解决方案5】:

    您可以通过引用列表中每一列的名称来沿 DataFrame 的列进行切片,如下所示:

    data = pandas.DataFrame(np.random.rand(10,5), columns = list('abcde'))
    data_ab = data[list('ab')]
    data_cde = data[list('cde')]
    

    【讨论】:

    • 所以如果我想要从'b'列开始的所有数据,我需要在data.columns中找到'b'的索引并执行 data[data.columns[1:]] ?这就是规范的操作方式?
    • 您的意思是要选择从“b”开始的所有列?
    • 是,或者选择给定范围内的所有列。
    • 我自己对 pandas 还很陌生,所以我不能说什么被认为是规范的。我会像你说的那样做,但是使用data.columns 上的get_loc 函数来确定'b' 列的索引或其他什么。
    【解决方案6】:

    如果你来这里是为了寻找分割两个列范围并将它们组合在一起(像我一样)你可以做类似的事情

    op = df[list(df.columns[0:899]) + list(df.columns[3593:])]
    print op
    

    这将创建一个新的数据框,其中前 900 列和(所有)列 > 3593(假设您的数据集中有大约 4000 列)。

    【讨论】:

    • 太好了,有人试过了……我想知道,这个 0:899 获得了前 900 列……他们为什么这样做?这根本不像 Python。在 python 中使用范围时,它始终是“直到”而不是“直到并包含”
    【解决方案7】:

    以下是您可以使用不同方法进行选择性列切片的方法,包括基于选择性标签、基于索引和基于选择性范围的列切片。

    In [37]: import pandas as pd    
    In [38]: import numpy as np
    In [43]: df = pd.DataFrame(np.random.rand(4,7), columns = list('abcdefg'))
    
    In [44]: df
    Out[44]: 
              a         b         c         d         e         f         g
    0  0.409038  0.745497  0.890767  0.945890  0.014655  0.458070  0.786633
    1  0.570642  0.181552  0.794599  0.036340  0.907011  0.655237  0.735268
    2  0.568440  0.501638  0.186635  0.441445  0.703312  0.187447  0.604305
    3  0.679125  0.642817  0.697628  0.391686  0.698381  0.936899  0.101806
    
    In [45]: df.loc[:, ["a", "b", "c"]] ## label based selective column slicing 
    Out[45]: 
              a         b         c
    0  0.409038  0.745497  0.890767
    1  0.570642  0.181552  0.794599
    2  0.568440  0.501638  0.186635
    3  0.679125  0.642817  0.697628
    
    In [46]: df.loc[:, "a":"c"] ## label based column ranges slicing 
    Out[46]: 
              a         b         c
    0  0.409038  0.745497  0.890767
    1  0.570642  0.181552  0.794599
    2  0.568440  0.501638  0.186635
    3  0.679125  0.642817  0.697628
    
    In [47]: df.iloc[:, 0:3] ## index based column ranges slicing 
    Out[47]: 
              a         b         c
    0  0.409038  0.745497  0.890767
    1  0.570642  0.181552  0.794599
    2  0.568440  0.501638  0.186635
    3  0.679125  0.642817  0.697628
    
    ### with 2 different column ranges, index based slicing: 
    In [49]: df[df.columns[0:1].tolist() + df.columns[1:3].tolist()]
    Out[49]: 
              a         b         c
    0  0.409038  0.745497  0.890767
    1  0.570642  0.181552  0.794599
    2  0.568440  0.501638  0.186635
    3  0.679125  0.642817  0.697628
    

    【讨论】:

    【解决方案8】:

    它的等价物

     >>> print(df2.loc[140:160,['Relevance','Title']])
     >>> print(df2.ix[140:160,[3,7]])
    

    【讨论】:

      【解决方案9】:

      另一种从 DataFrame 中获取列子集的方法(假设您想要所有行)是:
      data[['a','b']]data[['c','d','e']]
      如果您想使用数字列索引,您可以这样做:
      data[data.columns[:2]]data[data.columns[2:]]

      【讨论】:

        【解决方案10】:

        如果数据框看起来像这样:

        group         name      count
        fruit         apple     90
        fruit         banana    150
        fruit         orange    130
        vegetable     broccoli  80
        vegetable     kale      70
        vegetable     lettuce   125
        

        和 OUTPUT 可能是这样的

           group    name  count
        0  fruit   apple     90
        1  fruit  banana    150
        2  fruit  orange    130
        

        如果你使用逻辑运算符 np.logical_not

        df[np.logical_not(df['group'] == 'vegetable')]
        

        更多关于

        https://docs.scipy.org/doc/numpy-1.13.0/reference/routines.logic.html

        其他逻辑运算符

        1. logical_and(x1, x2, /[, out, where, ...]) 计算真值 x1 AND x2 逐元素。

        2. logical_or(x1, x2, /[, out, where, cast, ...]) 逐元素计算 x1 OR x2 的真值。

        3. logical_not(x, /[, out, where, cast, ...]) 计算真相 NOT x 元素的值。
        4. logical_xor(x1, x2, /[, out, where, ..]) 按元素计算 x1 XOR x2 的真值。

        【讨论】:

          【解决方案11】:

          可以使用truncate的方法

          df = pd.DataFrame(np.random.rand(10, 5), columns = list('abcde'))
          
          df_ab = df.truncate(before='a', after='b', axis=1)
          df_cde = df.truncate(before='c', axis=1)
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2018-07-14
            • 2021-03-20
            • 2021-12-04
            • 1970-01-01
            • 2021-07-23
            相关资源
            最近更新 更多