使用列名作为pandas DataFrame上where的条件

时间:2016-04-18 15:38:33

标签: python pandas

说我有以下DataFrame:

arrays = [['foo', 'foo', 'bar', 'bar'],
          ['A', 'B', 'C', 'D']]
tuples = list(zip(*arrays))          
columnValues = pd.MultiIndex.from_tuples(tuples)
df = pd.DataFrame(np.random.rand(4,4), columns = columnValues)
print(df)

             foo                 bar          
               A         B         C         D
0       0.037362  0.470010  0.315396  0.333798
1       0.339038  0.396307  0.487242  0.064883
2       0.691654  0.793609  0.044490  0.384154
3       0.605801  0.967021  0.156839  0.123816

我想生成以下输出:

             foo                 bar          
               A         B         C         D
0              0         0  0.315396  0.333798
1              0         0  0.487242  0.064883
2              0         0  0.044490  0.384154
3              0         0  0.156839  0.123816

我认为我可以使用pd.DataFrame.where(),但我不知道如何将列名称bar作为条件传递。

编辑:我正在寻找一种专门使用bar代替foo来产生所需结果的方法,因为foo实际上会有很多列

EDIT2:遗憾的是,如果列表包含所有列标签,则列表理解会中断。明确地写出for循环确实有效。 所以不要这样:

df.loc[:,  [col for col in df.columns.levels[0] if col != 'bar']] = 0 

我用这个:

for col in df.columns.levels[0]:
    if not(col in nameList):
        df.loc[:,col]=0

4 个答案:

答案 0 :(得分:2)

使用slicing设置您的数据。在这里,您可以访问foo下的子列(A,B)。

In [12]: df
Out[12]:
        foo                 bar
          A         B         C         D
0  0.040251  0.119267  0.170111  0.582362
1  0.978192  0.592043  0.515702  0.630627
2  0.762532  0.667234  0.450505  0.103858
3  0.871375  0.397503  0.966837  0.870184

In [13]: df.loc[:, 'foo'] = 0

In [14]: df
Out[14]:
  foo          bar
    A  B         C         D
0   0  0  0.170111  0.582362
1   0  0  0.515702  0.630627
2   0  0  0.450505  0.103858
3   0  0  0.966837  0.870184

如果您想设置除bar以外的所有列,您可以这样做。

In [15]: df.loc[:,  [col for col in df.columns.levels[0] if col != 'bar']] = 0

答案 1 :(得分:1)

我猜你可以使用get_level_values

>>> df
        foo                 bar          
          A         B         C         D
0  0.039728  0.065875  0.825380  0.240403
1  0.617857  0.895751  0.484237  0.506315
2  0.332381  0.047287  0.011291  0.346073
3  0.216224  0.024978  0.834353  0.500970
>>> df.loc[:, df.columns.get_level_values(0) != "bar"] = 0
>>> df
  foo          bar          
    A  B         C         D
0   0  0  0.825380  0.240403
1   0  0  0.484237  0.506315
2   0  0  0.011291  0.346073
3   0  0  0.834353  0.500970

df.columns.droplevel(1) != "bar"也应该有用,虽然我不喜欢它,尽管它更短,因为它反转了选择逻辑。

答案 2 :(得分:0)

更容易,没有loc

  

df [' foo'] = 0

答案 3 :(得分:0)

如果您没有这个多索引,可以使用:

df.ix[:,['A','B']] = 0

这会自动替换列中的值' A'和' B'由0。