在两列上使用pandas进行分解

时间:2017-08-08 17:30:28

标签: python python-3.x pandas

我在pandas数据框中有一些看起来像这样的数据;

CAR_TYPE   MILEAGE
FORD       100     
FORD       100    
FORD       200    
FORD       300
VW         100     
VW         150
VW         150
VW         300

我想“分解”数据以返回每对的唯一ID。但是我希望将独特的ID“重置”为零,以便单独制作汽车。目前我的分解使用以下内容;

df['CAR_ID']=pd.factorize(pd.lib.fast_zip([df.CAR_TYPE.values, df.MILEAGE.values]))[0] 
df.CAR_ID=df[['CAR_ID', 'CAR_TYPE']].astype(str).apply(lambda x: ''.join(x), axis=1)

给我一​​些像

的东西
CAR_TYPE   MILEAGE     CAR_ID  
FORD       100         FORD0
FORD       100         FORD0
FORD       200         FORD1
FORD       300         FORD2
VW         100         VW3
VW         150         VW4
VW         150         VW4
VW         300         VW5

理想情况下我想

CAR_TYPE   MILEAGE     IDEAL_CAR_ID  
FORD       100         FORD0
FORD       100         FORD0
FORD       200         FORD1
FORD       300         FORD2
VW         100         VW0
VW         150         VW1
VW         150         VW1
VW         300         VW2

对于相对愚蠢的问题道歉,经过漫长的一天后,他的斗智斗勇。我知道它可以用stack / unstack,reset_index / set_index来解决。

4 个答案:

答案 0 :(得分:3)

如果MILEAGE中的值按群组排序,则可以groupbyrank一起使用:

a = df.groupby(['CAR_TYPE'])['MILEAGE'].rank(method='dense') \
      .sub(1).astype(int).astype(str)
df['IDEAL_CAR_ID'] = df['CAR_TYPE'].add(a)
print (df)

  CAR_TYPE  MILEAGE IDEAL_CAR_ID
0     FORD      100        FORD0
1     FORD      100        FORD0
2     FORD      200        FORD1
3     FORD      300        FORD2
4       VW      100          VW0
5       VW      150          VW1
6       VW      150          VW1
7       VW      300          VW2

factorize的另一个解决方案:

a = df.groupby(['CAR_TYPE'])['MILEAGE'] \
       .transform(lambda x: pd.factorize(x)[0]).astype(str)
df['IDEAL_CAR_ID'] = df['CAR_TYPE'].add(a)
print (df)
  CAR_TYPE  MILEAGE IDEAL_CAR_ID
0     FORD      100        FORD0
1     FORD      100        FORD0
2     FORD      200        FORD1
3     FORD      300        FORD2
4       VW      100          VW0
5       VW      150          VW1
6       VW      150          VW1
7       VW      300          VW2

如果列未排序,则输出不同:

print (df)
  CAR_TYPE  MILEAGE
0     FORD      500
1     FORD      500
2     FORD      200
3     FORD      300
4       VW      100
5       VW      150
6       VW      150
7       VW      300

a = df.groupby(['CAR_TYPE'])['MILEAGE'].rank(method='dense') \
      .sub(1).astype(int).astype(str)
df['IDEAL_CAR_ID'] = df['CAR_TYPE'].add(a)
print (df)
  CAR_TYPE  MILEAGE IDEAL_CAR_ID
0     FORD      500        FORD2
1     FORD      500        FORD2
2     FORD      200        FORD0
3     FORD      300        FORD1
4       VW      100          VW0
5       VW      150          VW1
6       VW      150          VW1
7       VW      300          VW2
a = df.groupby(['CAR_TYPE'])['MILEAGE'] \
       .transform(lambda x: pd.factorize(x)[0]).astype(str)
df['IDEAL_CAR_ID'] = df['CAR_TYPE'].add(a)
print (df)
  CAR_TYPE  MILEAGE IDEAL_CAR_ID
0     FORD      500        FORD0
1     FORD      500        FORD0
2     FORD      200        FORD1
3     FORD      300        FORD2
4       VW      100          VW0
5       VW      150          VW1
6       VW      150          VW1
7       VW      300          VW2

答案 1 :(得分:2)

或者你可以试试这个。

{{1}}

答案 2 :(得分:2)

f1 = pd.factorize(list(zip(df.CAR_TYPE.values, df.MILEAGE.values)))[0]
f0 = pd.factorize(df.CAR_TYPE.values)[0] \
    * (df.groupby('CAR_TYPE').CAR_TYPE.transform('count').values - 1)

df.assign(CAR_ID=df.CAR_TYPE.add((f1 - f0).astype(str)))

  CAR_TYPE  MILEAGE CAR_ID
0     FORD      100  FORD0
1     FORD      100  FORD0
2     FORD      200  FORD1
3     FORD      300  FORD2
4       VW      100    VW0
5       VW      150    VW1
6       VW      150    VW1
7       VW      300    VW2

答案 3 :(得分:0)

这也可以通过使用groupby.ngroup()并使用.astype(str)转换为字符串,然后使用series.radd()将其添加到CAR_TYPE列来实现:

df['CAR_ID'] = (df.groupby(['CAR_TYPE','MILEAGE'],sort=False).ngroup()
                                    .astype(str).radd(df['CAR_TYPE']))

print(df)

  CAR_TYPE  MILEAGE CAR_ID
0     FORD      100  FORD0
1     FORD      100  FORD0
2     FORD      200  FORD1
3     FORD      300  FORD2
4       VW      100    VW3
5       VW      150    VW4
6       VW      150    VW4
7       VW      300    VW5

有关更多详细信息,请参见以下ngroup产生的内容:

print(df.groupby(['CAR_TYPE','MILEAGE'],sort=False).ngroup())

0    0
1    0
2    1
3    2
4    3
5    4
6    4
7    5