【发布时间】:2017-09-12 22:01:39
【问题描述】:
我有一个像这样的数据框:
A B C
1 0 0
1 1 0
0 1 0
0 0 1
我想要:
A B C label
1 0 0 A
1 1 0 AB
0 1 0 B
0 0 1 C
我尝试通过 map 或 apply 来做,但我想不通。
【问题讨论】:
我有一个像这样的数据框:
A B C
1 0 0
1 1 0
0 1 0
0 0 1
我想要:
A B C label
1 0 0 A
1 1 0 AB
0 1 0 B
0 0 1 C
我尝试通过 map 或 apply 来做,但我想不通。
【问题讨论】:
df = df.assign(label=[''.join([df.columns[n] for n, bool in enumerate(row) if bool])
for _, row in df.iterrows()])
>>> df
A B C label
0 1 0 0 A
1 1 1 0 AB
2 0 1 0 B
3 0 0 1 C
时间
# Set-up:
df_ = pd.concat([df] * 10000)
%%timeit
# Solution by @Wen
df1 = df_.reset_index().melt('index')
df1 = df1[df1.value==1]
df['label'] = df1.groupby('index').variable.sum()
# 10 loops, best of 3: 47.6 ms per loop
%%timeit
# Solution by @MaxU
df_['label'] = df_.apply(lambda x: ''.join(df_.columns[x.astype(bool)].tolist()), axis=1)
# 1 loop, best of 3: 4.99 s per loop
%%timeit
# Solution by @TedPetrou
df_['label'] = np.where(df_, df_.columns, '').sum(axis=1)
# 100 loops, best of 3: 12.5 ms per loop
%%timeit
# Solution by @Alexander
df_['label'] = [''.join([df_.columns[n] for n, bool in enumerate(row) if bool]) for _, row in df_.iterrows()]
# 1 loop, best of 3: 3.75 s per loop
%%time
# Solution by @PiRSquared
df_['label'] = df_.dot(df_.columns)
# CPU times: user 18.1 ms, sys: 706 µs, total: 18.8 ms
# Wall time: 18.9 ms
【讨论】:
这是一个惯用且高效的解决方案
df['label'] = np.where(df, df.columns, '').sum(axis=1)
A B C label
0 1 0 0 A
1 1 1 0 AB
2 0 1 0 B
3 0 0 1 C
【讨论】:
或者使用melt和groupby
df1 = df.reset_index().melt('index')
df1 = df1[df1.value==1]
df['label'] = df1.groupby('index').variable.sum()
df
Out[976]:
A B C label
0 1 0 0 A
1 1 1 0 AB
2 0 1 0 B
3 0 0 1 C
或者
df['label'] = df.T.apply(lambda x: ''.join(x.index[x==1]),axis=0)
df
Out[984]:
A B C label
0 1 0 0 A
1 1 1 0 AB
2 0 1 0 B
3 0 0 1 C
【讨论】:
使用dot
df.assign(label=df.dot(df.columns))
A B C label
0 1 0 0 A
1 1 1 0 AB
2 0 1 0 B
3 0 0 1 C
使用底层 numpy 数组也是如此
df.assign(label=df.values.dot(df.columns.values))
A B C label
0 1 0 0 A
1 1 1 0 AB
2 0 1 0 B
3 0 0 1 C
【讨论】:
df.dot(df.columns) 很好。
df.columns.values 属于dtype object 的敏锐观察。以下失败 df.values.dot(df.columns.values.astype(str)) 和 np.where(df, df.columns, '').astype(str).sum(axis=1)
In [101]: df['label'] = df.apply(lambda x: ''.join(df.columns[x.astype(bool)].tolist()), axis=1)
In [102]: df
Out[102]:
A B C label
0 1 0 0 A
1 1 1 0 AB
2 0 1 0 B
3 0 0 1 C
PS 我肯定会选择@Ted's solution,因为它更好,而且更快……更快
【讨论】: