添加"标志"关于一个ID是否在另一列中具有特定值的列

时间:2017-06-02 08:06:21

标签: python pandas dataframe group-by

数据框如下:

 In [1]: df
 Out[2]:
          userid type
    0      1       1
    1      1       2
    2      2       1
    3      3       1
    4      3       2
    5      3       3    

现在我想为它添加一个关于userid是否在" type"中有特定值的列。列(让我们说type1和type2)。 这就是我想要的输出:

 In [1]: df
 Out[2]:
          userid type  has_type_12
    0      1       1      1
    1      1       2      1
    2      2       1      0
    3      3       1      1
    4      3       2      1
    5      3       3      1

对此有快速解决方案吗?

我遗漏了一种情况,其中userID 3可能有更多类型,如3或4.在这种情况下,我想标记has_type_12 = 1为3.我修改了输入和上面所需的输出。

4 个答案:

答案 0 :(得分:4)

In [308]: df['has_type_12'] = \
              df.groupby('userid')['type'].transform(lambda x: x[x.isin([1,2])].nunique() == 2)

In [309]: df
Out[309]:
   userid  type  has_type_12
0       1     1            1
1       1     2            1
2       2     1            0
3       3     1            1
4       3     2            1
5       3     3            1

答案 1 :(得分:3)

groupby + transformset s:

一起使用
cats = [1,2]
df['has_type_12'] = df.groupby('userid')['type'] \
                      .transform(lambda x: set(x) >= set((cats))) \
                      .astype(int) 
print (df)
   userid  type  has_type_12
0       1     1            1
1       1     2            1
2       2     1            0
3       3     1            1
4       3     2            1
5       3     3            1

使用双any的另一种解决方案(如果只有几个类别):

cats = [1,2]
df['has_type_12'] = df.groupby('userid')['type'] \
                      .transform(lambda x: ((x == 1).any()) & ((x == 2).any())) \
                      .astype(int) 
print (df)
   userid  type  has_type_12
0       1     1            1
1       1     2            1
2       2     1            0
3       3     1            1
4       3     2            1
5       3     3            1

答案 2 :(得分:2)

使用set时,>=运算符会测试右侧是否是左侧的子集。我使用ge方法作为>=

的代理

使用groupby

m = df.groupby('userid').type.apply(set)
df.assign(
  has_type_12=df.userid.map(m).ge({1, 2}).astype(int)
)

   userid  type  has_type_12
0       1     1            1
1       1     2            1
2       2     1            0
3       3     1            1
4       3     2            1
5       3     3            1

使用defaultdict

from collections import defaultdict

d = defaultdict(set)
[d[k].add(v) for k, v in zip(df.userid.values.tolist(), df.type.values.tolist())];
df.assign(has_type_12=df.userid.map(d).ge({1, 2}).astype(int))

   userid  type  has_type_12
0       1     1            1
1       1     2            1
2       2     1            0
3       3     1            1
4       3     2            1
5       3     3            1

<强>时序
大数据

np.random.seed([3,1415])
df = pd.DataFrame(dict(
        userid=np.random.randint(1000, size=100000),
        type=np.random.randint(100, size=100000)
    ))

%%timeit
d = defaultdict(set)
[d[k].add(v) for k, v in zip(df.userid.values.tolist(), df.type.values.tolist())];
df.userid.map(d).ge({1, 2}).astype(int)
10 loops, best of 3: 55.6 ms per loop

%%timeit 
m = df.groupby('userid').type.apply(set)
df.userid.map(m).ge({1, 2}).astype(int)
10 loops, best of 3: 76.1 ms per loop

%timeit df.groupby('userid')['type'] \
                      .transform(lambda x: set(x) >= set((cats))) \
                      .astype(int)
1 loop, best of 3: 206 ms per loop

答案 3 :(得分:0)

使用groupby并为每次使用获取唯一类型ID,然后检查它是否包含{1,2}。

df['has_type_12'] = df.groupby('userid')['type']\
  .apply(lambda x: set(x).issuperset({1,2}))\
  .astype(int).values[df.userid]