Selecting/excluding sets of columns in pandas
我希望基于列选择从现有数据帧创建视图或数据帧。
例如,我想从一个数据帧
1 2 3 4 5 6 7 8 9 10 11 12 | 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] |
我做错什么了?也许更一般地说,熊猫需要什么机制来支持从数据帧中挑选和排除任意列集?
您可以删除不需要的列,也可以选择需要的列。
1 2 3 4 5 6 7 8 | # 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']] |
有一种新的索引方法叫做
1 | df2 = df[df.columns.difference(['B', 'D'])] |
这里,输出用于从
您不需要将其转换为集合:
1 2 | cols = [col for col in df.columns if col not in ['B', 'D']] df2 = df[cols] |
另一个选项,不在循环中删除或过滤:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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'])]] |
还可以查看内置的
最小但贪婪的方法(对于给定的df足够):
1 | df.filter(regex="[^BD]") |
保守/懒惰方法(仅限精确匹配):
1 | df.filter(regex="^(?!(B|D)$).*$") |
保守和一般:
1 2 | exclude_cols = ['B','C'] df.filter(regex="^(?!({0})$).*$".format('|'.join(exclude_cols))) |
你只需要把你的
1 2 3 4 5 6 7 | 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] |
以下是如何创建
1 2 | df = pd.DataFrame(np.random.randn(100, 4), columns=list('ABCD')) df2 = df.drop(['B', 'D'], axis=1) |
但是要小心!你在问题中提到了一些观点,暗示如果你改变了
这种方法无法实现:
1 2 3 4 5 6 7 | >>> 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的方法也是如此。(尽管这种方法很好,而且很巧妙,而且是Python式的。我不是在做下去!!)
有关视图和副本的更多信息,请参阅此答案和此答案所指的熊猫文档部分。
有4列A、B、C、D
以下是选择新数据帧所需列的更好方法:
1 | df2 = df1[['A','D']] |
如果要使用列号,请使用-
1 | df2 = df1[[0,3]] |
以类似的方式,在读取文件时,可能希望预先排除列,而不是浪费地将不需要的数据读取到内存中,然后丢弃它们。
从pandas 0.20.0开始,
1 2 | skipcols = [...] read_csv(..., usecols=lambda x: x not in skipcols) |
后一种模式本质上与传统的
鉴于
文件中的数据
1 2 3 4 5 6 7 8 | 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) |
代码
1 2 3 | skipcols = ["B","D"] df1 = pd.read_csv(filename, usecols=lambda x: x not in skipcols, index_col=0) df1 |
产量
1 2 3 4 5 6 7 | 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 ... |
细节
数据帧被写入文件。然后它被作为一个单独的数据帧读回,现在跳过不需要的列(
注意,对于OP的情况,由于已经创建了数据,所以更好的方法是接受的答案,它从现有对象中删除不需要的列。但是,在将文件中的数据直接读取到数据帧中时,这里介绍的技术最有用。
a request was provided for a"skipcols"option in this issue and was addressed in a later issue.