448

我想根据列选择从现有数据框创建视图或数据框。

例如,我想df2从一个数据框创建一个数据框,该数据框df1包含除其中两个之外的所有列。我尝试执行以下操作,但没有成功:

import numpy as np
import pandas as pd

# Create a dataframe with columns A,B,C and D
df = pd.DataFrame(np.random.randn(100, 4), columns=list('ABCD'))

# Try to create a second dataframe df2 from df with all columns except 'B' and D
my_cols = set(df.columns)
my_cols.remove('B').remove('D')

# This returns an error ("unhashable type: set")
df2 = df[my_cols]

我究竟做错了什么?也许更一般地说,pandas 有什么机制来支持从数据帧中选择和排除任意列集?

4

9 回答 9

646

您可以删除不需要的列或选择您需要的列

# Using DataFrame.drop
df.drop(df.columns[[1, 2]], axis=1, inplace=True)

# drop by Name
df1 = df1.drop(['B', 'C'], axis=1)

# Select the ones you want
df1 = df[['a','d']]
于 2015-03-28T15:54:50.590 回答
209

有一种新的索引方法称为difference. 它返回原始列,并删除作为参数传递的列。

在这里,结果用于删除列BDdf

df2 = df[df.columns.difference(['B', 'D'])]

请注意,它是基于集合的方法,因此重复的列名会导致问题,并且可能会更改列顺序。


优势:当您只需要列列表时,drop您不会创建整个数据框的副本。例如,为了在列的子集上删除重复项:

# may create a copy of the dataframe
subset = df.drop(['B', 'D'], axis=1).columns

# does not create a copy the dataframe
subset = df.columns.difference(['B', 'D'])

df = df.drop_duplicates(subset=subset)
于 2016-05-25T15:12:27.937 回答
131

另一种选择,无需在循环中丢弃或过滤:

import numpy as np
import pandas as pd

# Create a dataframe with columns A,B,C and D
df = pd.DataFrame(np.random.randn(100, 4), columns=list('ABCD'))

# include the columns you want
df[df.columns[df.columns.isin(['A', 'B'])]]

# or more simply include columns:
df[['A', 'B']]

# exclude columns you don't want
df[df.columns[~df.columns.isin(['C','D'])]]

# or even simpler since 0.24
# with the caveat that it reorders columns alphabetically 
df[df.columns.difference(['C', 'D'])]
于 2018-07-30T20:41:25.670 回答
81

你真的不需要把它转换成一个集合:

cols = [col for col in df.columns if col not in ['B', 'D']]
df2 = df[cols]
于 2013-11-18T02:25:39.110 回答
22

也看看内置DataFrame.filter函数。

简约但贪婪的方法(对于给定的 df 足够了):

df.filter(regex="[^BD]")

保守/惰性方法(仅精确匹配):

df.filter(regex="^(?!(B|D)$).*$")

保守和通用:

exclude_cols = ['B','C']
df.filter(regex="^(?!({0})$).*$".format('|'.join(exclude_cols)))
于 2014-10-14T09:02:31.400 回答
11

您有 4 列 A、B、C、D

这是为新数据框选择所需列的更好方法:-

df2 = df1[['A','D']]

如果您想改用列号,请使用:-

df2 = df1[[0,3]]
于 2018-06-18T13:56:12.280 回答
9

您只需要将您的转换setlist

import pandas as pd
df = pd.DataFrame(np.random.randn(100, 4), columns=list('ABCD'))
my_cols = set(df.columns)
my_cols.remove('B')
my_cols.remove('D')
my_cols = list(my_cols)
df2 = df[my_cols]
于 2013-02-18T16:32:43.187 回答
7

以下是创建不包括列列表的副本的方法:DataFrame

df = pd.DataFrame(np.random.randn(100, 4), columns=list('ABCD'))
df2 = df.drop(['B', 'D'], axis=1)

但小心点!你在你的问题中提到了观点,暗示如果你改变了df,你也想df2改变。(就像数据库中的视图一样。)

此方法无法实现:

>>> df.loc[0, 'A'] = 999 # Change the first value in df
>>> df.head(1)
     A         B         C         D
0  999 -0.742688 -1.980673 -0.920133
>>> df2.head(1) # df2 is unchanged. It's not a view, it's a copy!
          A         C
0  0.251262 -1.980673

另请注意,@piggybox 的方法也是如此。(虽然这种方法很好,很漂亮,而且 Pythonic。我不会这样做!!)

有关视图与副本的更多信息,请参阅此 SO 答案以及该答案所指的 Pandas 文档的这一部分。

于 2014-08-23T18:45:39.123 回答
5

类似地,在读取文件时,可能希望预先排除列,而不是浪费地将不需要的数据读入内存然后丢弃它们。

从 pandas 0.20.0 开始,usecols现在接受 callables1 此更新允许更灵活的选项来读取列:

skipcols = [...]
read_csv(..., usecols=lambda x: x not in skipcols)

后一种模式本质上与传统usecols方法相反——仅跳过指定的列。


给定

文件中的数据

import numpy as np
import pandas as pd


df = pd.DataFrame(np.random.randn(100, 4), columns=list('ABCD'))

filename = "foo.csv"
df.to_csv(filename)

代码

skipcols = ["B", "D"]
df1 = pd.read_csv(filename, usecols=lambda x: x not in skipcols, index_col=0)
df1

输出

          A         C
0  0.062350  0.076924
1 -0.016872  1.091446
2  0.213050  1.646109
3 -1.196928  1.153497
4 -0.628839 -0.856529
...

细节

将 DataFrame 写入文件。然后它作为一个单独的 DataFrame 被读回,现在跳过不需要的列(BD)。

请注意,对于 OP 的情况,由于已经创建了数据,因此更好的方法是接受的答案,即从现有对象中删除不需要的列。但是,这里介绍的技术在直接将文件中的数据读取到 DataFrame 时最有用。

在这个问题中提出了一个“skipcols”选项的请求,并在以后的问题中得到解决。

于 2017-11-22T02:06:00.470 回答