2016-06-09 51 views
1

我想获得电话号码和值的独特组合,其中电话号码和值分别位于两个潜在列中。Python熊猫 - 多个特定列中的变量的独特组合

例如:

df = pd.DataFrame({'phone1':[4567890876, 4567890876, 9178889999, 3237800876], 
        'phone2':[4567890876, 4567890876, 9178889999, 2139990000], 
        'num1':[1,2,3,3], 
        'num2':[5,2,3,1]}) 

的唯一值的样子:

phone   num 
4567890876 1 
4567890876 2 
4567890876 5 
9178889999 3 
2139990000 1 
2139990000 3 
3237800876 1 
3237800876 3 

我发现两种方法可以做到这一点,但他们都觉得很笨拙/错误:

1)复制df四次(phone1/num1,phone1/num2,phone2/num1,phone2/num2),连接并丢弃重复项

2)通过手机字段进行索引,堆叠,然后通过数字字段进行索引并重新堆叠,然后删除重复副本

如果有人有更好/更清洁/更快的创意,将不胜感激!

+0

为什么'2139990000'和'3237800876'在结果DF中出现两次? – MaxU

回答

2

pd.melt可以将多个列合并为一个值列(和一个可变列)。你可以使用它曾经凝聚了num1num2列,和第二次聚结phone1phone2列:

import pandas as pd 
df = pd.DataFrame({'phone1':[4567890876, 4567890876, 9178889999, 3237800876], 
        'phone2':[4567890876, 4567890876, 9178889999, 2139990000], 
        'num1':[1,2,3,3], 
        'num2':[5,2,3,1]}) 

melted = pd.melt(df, id_vars=['phone1', 'phone2'], var_name='numvar', value_name='num') 
melted = pd.melt(melted, id_vars=['numvar', 'num'], value_name='phone') 
melted = melted[['num', 'phone']] 
melted = melted.drop_duplicates() 
print(melted) 

产生

num  phone 
0  1 4567890876 
1  2 4567890876 
2  3 9178889999 
3  3 3237800876 
4  5 4567890876 
7  1 3237800876 
11 3 2139990000 
15 1 2139990000 

说明:使用id_vars到防止phone1phone2色谱柱熔化。下面显示熔化num1num2列结果:

In [166]: melted = pd.melt(df, id_vars=['phone1', 'phone2'], var_name='numvar', value_name='num'); melted 
Out[166]: 
     phone1  phone2 numvar num 
0 4567890876 4567890876 num1 1 
1 4567890876 4567890876 num1 2 
2 9178889999 9178889999 num1 3 
3 3237800876 2139990000 num1 3 
4 4567890876 4567890876 num2 5 
5 4567890876 4567890876 num2 2 
6 9178889999 9178889999 num2 3 
7 3237800876 2139990000 num2 1 

然后再次申请pd.meltphone1phone2列合并为一个:

In [168]: pd.melt(melted, id_vars=['numvar', 'num'], value_name='phone') 
Out[168]: 
    numvar num variable  phone 
0 num1 1 phone1 4567890876 
1 num1 2 phone1 4567890876 
2 num1 3 phone1 9178889999 
3 num1 3 phone1 3237800876 
4 num2 5 phone1 4567890876 
5 num2 2 phone1 4567890876 
6 num2 3 phone1 9178889999 
7 num2 1 phone1 3237800876 
8 num1 1 phone2 4567890876 
9 num1 2 phone2 4567890876 
10 num1 3 phone2 9178889999 
11 num1 3 phone2 2139990000 
12 num2 5 phone2 4567890876 
13 num2 2 phone2 4567890876 
14 num2 3 phone2 9178889999 
15 num2 1 phone2 2139990000 

删除重复项,并删除numvarvariable列你会得到想要的结果(尽管顺序不同)。

+0

你的第一个解决方案有什么问题 - 'lreshape()'?我更喜欢它:) – MaxU

+1

@MaxU:'pd.lreshape(df,{'phone':['phone1','phone2'],'num':['num1','num2']})。drop_duplicates( )'有正确的形式,但是给出了错误的结果。它的作用就像连接phone1和phone2列一样,对于num1和num2列也是如此,但它不会将num1和* phone1和phone2关联起来,也不会关联'num2'包含'phone'列。它只把'num1'与'phone1'和'num2'与'phone2'联系起来。 – unutbu

+0

感谢您的解释! – MaxU