我在下面有一张桌子。我想使用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
答案 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]