遍历每一行值并返回列名

时间:2018-11-10 15:57:17

标签: python pandas

我在下面有一张桌子。我想使用python和pandas返回表中每一行的haves列,其中行值等于1的列名。

# A tibble: 5 x 2
  a         b
  <chr> <int>
1 50       50
2 20       20
3 13       13
4 grp2     20
5 grp1      7

3 个答案:

答案 0 :(得分:1)

首先将eq==)与具有列名的dot产品进行比较,如果性能很重要,最后通过rstrip除去最后一个分隔符值

df['haves'] = df.eq(1).dot(df.columns + ', ').str.rstrip(', ')
#solution with omiting first column
#df['haves'] = df.iloc[:, 1:].eq(1).dot(df.columns[1:] + ', ').str.rstrip(', ')
print (df)
  Location  House  car  Toys       haves
0        x      1    1     3  House, car
1        y      2    1     1   car, Toys

详细信息

print (df.eq(1))
   Location  House   car   Toys
0     False   True  True  False
1     False  False  True   True

print (df.eq(1).dot(df.columns + ', '))
0    House, car, 
1     car, Toys, 
dtype: object

性能:取决于1值的数量,列和行的数量,但是由于dot是矢量化的,因此它比循环解决方案更快:

#2k rows
df = pd.concat([df] * 1000, ignore_index=True)

In [183]: %timeit df['haves'] = df.eq(1).dot(df.columns + ', ').str.rstrip(', ')
2.65 ms ± 34.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

#working if no missing values 
In [184]: %timeit df['haves'] = [x.rstrip(', ') for x in df.eq(1).dot(df.columns + ', ')]
2.43 ms ± 38.5 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

#jpp answer
In [185]: %timeit df['haves'] = [', '.join(df.columns[1:][idx]) for idx in df.iloc[:, 1:].eq(1).values]
86.5 ms ± 4.32 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

#Naga Kiran removed answer
In [186]: %timeit df['have'] = df.apply(lambda x: ','.join(x[x.eq(1)].index),1)
813 ms ± 8.66 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

答案 1 :(得分:0)

假设您需要创建45 系列,则可以使用列表推导:

haves

我不认为此任务很容易实现矢量化,因为您可以拥有数量不等的满足您条件的值,并且您的结果将是df['haves'] = [', '.join(df.columns[1:][idx]) for idx in df.iloc[:, 1:].eq(1).values] print(df) Location House car Toys haves 0 x 1 1 3 House, car 1 y 2 1 1 car, Toys dtype系列。

答案 2 :(得分:0)

这是一种简单的方法,仅比点方法慢一点,并且可能更易于理解。它确实使用numpy创建了cols数组,与仅使用df.columns作为列表相比,它大大提高了速度。

import numpy as np

# numpy array of dataframe column names
cols = np.array(df.columns)
# boolean array to mark where dataframe values equal 1
b = (df.values == 1)
# list comprehension to join column names for each boolean row result
df['haves'] = [', '.join(cols[(row_index)]) for row_index in b]