np.where索引大于特定值

时间:2018-06-29 04:43:01

标签: python pandas numpy pandas-groupby

我以为这很简单,但是显然我在这里遗漏了一些东西。

我希望能够将np.wheredf.groupby('Name').apply()一起使用,以在df中创建新列(称为'New'),其中列的值为{ {1}}如果各个组的索引(对应于原始1的索引)大于或等于(df)个特定值,则为>=

对于背景,我将0df列分组,并且我有一个'Name',其中包含用于dict()中每个名称的对应值。我希望很清楚,如有必要,我可以提供进一步的澄清。

给定示例groupby(),这是我到目前为止的内容:

df

然后我使用以下方法在df = pd.DataFrame([['William', 1, 0, 0, 0, 1],['James', 0, 1, 1, 1, 1],['James', 1, 0, 0, 0, 0], ['James', 1, 0, 1, 1, 0],['William', 0, 1, 1, 0, 1],['William', 0, 0, 0, 0, 0], ['William', 1, 0, 1, 1, 0],['James', 0, 1, 1, 0, 1],['James', 0, 0, 0, 0, 0]], columns=['Name','x1','x2','x3','x4','Interest']) Name x1 x2 x3 x4 Interest 0 William 1 0 0 0 1 1 James 0 1 1 1 1 2 James 1 0 0 0 0 3 James 1 0 1 1 0 4 William 0 1 1 0 1 5 William 0 0 0 0 0 6 William 1 0 1 1 0 7 James 0 1 1 0 1 8 James 0 0 0 0 0 列具有df的每个组中找到'Interest'的最后一行:

1

注意:这是一个简化的示例。对于我的实际应用程序,我将第三行的索引拉到最后一行(即mydict = df[df['Interest']==1].groupby('Name').apply(lambda x: x.index[-1]).to_dict() {'James': 7, 'William': 4} ),但是下一部分是我的问题的根源所在。

现在,我想创建一个新列.apply(lambda x: x.index[-3]).to_dict(),如果行索引为'Name'该组的1中的值,则值为>=,否则mydict。我已经尝试了几件事:

0

显然,这将覆盖对for key, val in mydict.items(): df['New'] = np.where((df['Name']==key) & (df.index>=val), 1, 0) 所做的所有操作,并仅返回'James'的正确列。我该如何有效地做到这一点?

更确切地说,这是我的预期输出:

'William'

2 个答案:

答案 0 :(得分:3)

使用map

df.assign(New=(df.index >= df.Name.map(mydict)).astype(int))

      Name  x1  x2  x3  x4  Interest  New
0  William   1   0   0   0         1    0
1    James   0   1   1   1         1    0
2    James   1   0   0   0         0    0
3    James   1   0   1   1         0    0
4  William   0   1   1   0         1    1
5  William   0   0   0   0         0    1
6  William   1   0   1   1         0    1
7    James   0   1   1   0         1    1
8    James   0   0   0   0         0    1

答案 1 :(得分:2)

对所有掩码使用列表推导,然后reduce将它们掩码为一个,最后将其转换为整数-True s为1 s:

m = [((df['Name']==key) & (df.index>=val)) for key, val in mydict.items()]
print (m)
[0    False
1    False
2    False
3    False
4    False
5    False
6    False
7     True
8     True
Name: Name, dtype: bool, 0    False
1    False
2    False
3    False
4     True
5     True
6     True
7    False
8    False
Name: Name, dtype: bool]

df['New'] = np.logical_or.reduce(m).astype(int)
print (df)
      Name  x1  x2  x3  x4  Interest  New
0  William   1   0   0   0         1    0
1    James   0   1   1   1         1    0
2    James   1   0   0   0         0    0
3    James   1   0   1   1         0    0
4  William   0   1   1   0         1    1
5  William   0   0   0   0         0    1
6  William   1   0   1   1         0    1
7    James   0   1   1   0         1    1
8    James   0   0   0   0         0    1

编辑:

该问题的另一种解决方案:

df = pd.concat([df] * 2, ignore_index=True)

获取每个条件的第一个True值的索引-从后面计算第三个值

idx = df[df['Interest']==1].groupby('Name').cumcount(ascending=False).eq(2).idxmax()

将值从idx设置为1:

df['New'] = 0
df.loc[idx:, 'New'] = 1
print (df)
       Name  x1  x2  x3  x4  Interest  New
0   William   1   0   0   0         1    0
1     James   0   1   1   1         1    0
2     James   1   0   0   0         0    0
3     James   1   0   1   1         0    0
4   William   0   1   1   0         1    1
5   William   0   0   0   0         0    1
6   William   1   0   1   1         0    1
7     James   0   1   1   0         1    1
8     James   0   0   0   0         0    1
9   William   1   0   0   0         1    1
10    James   0   1   1   1         1    1
11    James   1   0   0   0         0    1
12    James   1   0   1   1         0    1
13  William   0   1   1   0         1    1
14  William   0   0   0   0         0    1
15  William   1   0   1   1         0    1
16    James   0   1   1   0         1    1
17    James   0   0   0   0         0    1

详细信息

print (df[df['Interest']==1].groupby('Name').cumcount(ascending=False))
0     3
1     3
4     2
7     2
9     1
10    1
13    0
16    0
dtype: int64
相关问题