连接文本&;python/pandas中的数字
我有一个连接文本&;python/pandas中的数字,python,pandas,numpy,Python,Pandas,Numpy,我有一个数据帧,如下所示 +---+---+---+ | A | B | C | +---+---+---+ | 1 | 0 | 0 | +---+---+---+ | 0 | 0 | 1 | +---+---+---+ | 2 | 1 | 1 | +---+---+---+ | 3 | 1 | 2 | +---+---+---+ | 4 | 2 | 3 | +---+---+---+ df = pd.DataFrame({ 'A':[1,0,2,3,4], 'B':[0,0,
数据帧
,如下所示
+---+---+---+
| A | B | C |
+---+---+---+
| 1 | 0 | 0 |
+---+---+---+
| 0 | 0 | 1 |
+---+---+---+
| 2 | 1 | 1 |
+---+---+---+
| 3 | 1 | 2 |
+---+---+---+
| 4 | 2 | 3 |
+---+---+---+
df = pd.DataFrame({
'A':[1,0,2,3,4],
'B':[0,0,1,1,2],
'C':[0,1,1,2,3]
})
我的目标是将每个元素与其对应的列名连接起来,并生成一个系列
我在下面试过了
df.dot(df.columns +', ').str[:-2]
我得到的是
+---------------------------+
| A |
+---------------------------+
| C |
+---------------------------+
| A, A, B, C |
+---------------------------+
| A, A, A, B, C, C |
+---------------------------+
| A, A, A, A, B, B, C, C, C |
+---------------------------+
但是,我想要的是
+------------+
| A |
+------------+
| C |
+------------+
| 2A, B, C |
+------------+
| 3A, B, 2C |
+------------+
| 4A, 2B, 3C |
+------------+
我应该如何更改代码来实现这一点?使用lambda函数的一个想法:
f = lambda x: ', '.join(f'{v}{k}' if v != 1 else k for k, v in x[x > 0].items())
df = df.apply(f, axis=1)
print (df)
0 A
1 C
2 2A, B, C
3 3A, B, 2C
4 4A, 2B, 3C
dtype: object
熔化的另一个想法是,删除0
行,用列名连接数字,最后在groupby
中连接:
df = df.melt(ignore_index=False)
df = df[df['value'].ne(0)]
df['variable'] = df['value'].mask(df['value'].eq(1), '').astype(str) + df['variable']
df = df.groupby(level=0)['variable'].agg(', '.join)
print (df)
0 A
1 C
2 2A, B, C
3 3A, B, 2C
4 4A, 2B, 3C
Name: variable, dtype: object
解决此问题的另一种方法是使用集合.计数器
和列表理解
:
In [416]: from collections import Counter
In [403]: y = df.dot(df.columns).tolist()
In [420]: ans = [' ,'.join({k: (str(v)+k if v > 1 else k) for k,v in Counter(i).items()}.values()) if len(i) > 1 else i for i in y]
In [421]: pd.DataFrame(ans)
Out[421]:
0
0 A
1 C
2 2A ,B ,C
3 3A ,B ,2C
4 4A ,2B ,3C
解决方案的性能:
@捷瑞尔解决方案:
In [427]: def j():
...: f = lambda x: ', '.join(f'{v}{k}' if v != 1 else k for k, v in x[x > 0].items())
...: df.apply(f, axis=1)
...:
In [428]: %timeit j()
1.22 ms ± 47.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
In [434]: def j1():
...: x = df.melt(ignore_index=False)
...: x = x[x['value'].ne(0)]
...: x['variable'] = x['value'].mask(x['value'].eq(1), '').astype(str) + x['variable']
...: x = x.groupby(level=0)['variable'].agg(', '.join)
...:
In [435]: %timeit j1()
3.19 ms ± 139 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
我的解决方案:
In [429]: def m():
...: y = df.dot(df.columns).tolist()
...: ans = [' ,'.join({k: (str(v)+k if v > 1 else k) for k,v in Counter(i).items()}.values()) if len(i) > 1 else i for i in y]
...: pd.DataFrame(ans)
...:
In [430]: %timeit m()
213 µs ± 3.87 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
请看一下我的答案,投赞成票。!这很有效。我第一次遇到“来自集合导入计数器”。谢谢@汤米,我还增加了性能。我的解决方案最快。太棒了。!干杯