在pandas的数据框中的每一行中找到非零值的列索引集

时间:2015-09-24 18:36:38

标签: python pandas

有没有一种很好的方法可以在pandas的数据框中的每一行中找到非零值的列索引集?我是否必须逐行遍历数据框? 例如,数据框是 c1 c2 c3 c4 c5 c6 c7 c8 c9  1 1 0 0 0 0 0 0 0  1 0 0 0 0 0 0 0 0  0 1 0 0 0 0 0 0 0  1 0 0 0 0 0 0 0 0  0 1 0 0 0 0 0 0 0  0 0 0 0 0 0 0 0 0  0 2 1 1 1 1 1 0 2  1 5 5 0 0 1 0 4 6  4 3 0 1 1 1 1 5 10  3 5 2 4 1 2 2 1 3  6 4 0 1 0 0 0 0 0  3 9 1 0 1 0 2 1 0 预计产量将是 [ 'C1', 'C2'] [ 'C1'] [ 'C2'] ...

3 个答案:

答案 0 :(得分:6)

似乎你必须按行遍历DataFrame。

cols = df.columns
bt = df.apply(lambda x: x > 0)
bt.apply(lambda x: list(cols[x.values]), axis=1)

你会得到:

0                                 [c1, c2]
1                                     [c1]
2                                     [c2]
3                                     [c1]
4                                     [c2]
5                                       []
6             [c2, c3, c4, c5, c6, c7, c9]
7                 [c1, c2, c3, c6, c8, c9]
8         [c1, c2, c4, c5, c6, c7, c8, c9]
9     [c1, c2, c3, c4, c5, c6, c7, c8, c9]
10                            [c1, c2, c4]
11                [c1, c2, c3, c5, c7, c8]
dtype: object

如果性能很重要,请尝试将raw=True传递给布尔数据框架,如下所示:

%timeit df.apply(lambda x: x > 0, raw=True).apply(lambda x: list(cols[x.values]), axis=1)
1000 loops, best of 3: 812 µs per loop

它为您带来更好的性能提升。以下是raw=False(默认值)结果:

%timeit df.apply(lambda x: x > 0).apply(lambda x: list(cols[x.values]), axis=1)
100 loops, best of 3: 2.59 ms per loop

答案 1 :(得分:2)

可能堆叠的更好的数据结构(而不​​是一系列列表):

In [11]: res = df[df!=0].stack()

In [12]: res
Out[12]:
0   c1     1
    c2     1
1   c1     1
2   c2     1
3   c1     1
...

你可以遍历原始行:

In [13]: res.loc[0]
Out[13]:
c1    1
c2    1
dtype: float64

In [14]: res.loc[0].index
Out[14]: Index(['c1', 'c2'], dtype='object')

注意:我以为你以前能够在apply中返回一个列表(创建一个包含列表元素的DataFrame),这似乎不再是这种情况。

答案 2 :(得分:2)

这种做法怎么样?

#create a True / False data frame
df_boolean = df>0

#a little helper method that uses boolean slicing internally 
def bar(x,columns):
    return ','.join(list(columns[x]))

#use an apply along the column axis
df_boolean['result'] = df_boolean.apply(lambda x: bar(x,df_boolean.columns),axis=1)

# filter out the empty "rows" adn grab the result column
df_result =  df_boolean[df_boolean['result'] != '']['result']

#append an axis, just so each line will will output a list 
lst_result = df_result.values[:,np.newaxis]

print '\n'.join([ str(myelement) for myelement in lst_result])

这会产生:

['c1,c2']
['c1']
['c2']
['c1']
['c2']
['c2,c3,c4,c5,c6,c7,c9']
['c1,c2,c3,c6,c8,c9']
['c1,c2,c4,c5,c6,c7,c8,c9']
['c1,c2,c3,c4,c5,c6,c7,c8,c9']
['c1,c2,c4']
['c1,c2,c3,c5,c7,c8']