连接文本&;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)

请看一下我的答案,投赞成票。!这很有效。我第一次遇到“来自集合导入计数器”。谢谢@汤米,我还增加了性能。我的解决方案最快。太棒了。!干杯