我以为这很简单,但是显然我在这里遗漏了一些东西。
我希望能够将np.where
与df.groupby('Name').apply()
一起使用,以在df
中创建新列(称为'New'
),其中列的值为{ {1}}如果各个组的索引(对应于原始1
的索引)大于或等于(df
)个特定值,则为>=
。
对于背景,我将0
按df
列分组,并且我有一个'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'
答案 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