[英]Insert value from iterator to a pandas column based on condition
假设有一个像这样的 dataframe
A
0 -1
1 -1
2 1
3 0
4 -2
5 3
6 0
我想在 A 列A
值为负数的每一行中添加一个具有增量值的新列。
A B
0 -1 1
1 -1 2
2 1 nan
3 0 nan
4 -2 3
5 3 nan
6 0 nan
这是我的代码
ids = iter(range(1, np.sum((df['A'] < 0).values.ravel()) + 1))
df['B'] = np.where(df['A'] < 0, next(ids), np.nan)
不幸的是,我得到的是
A B
0 -1 1
1 -1 1
2 1 nan
3 0 nan
4 -2 1
5 3 nan
6 0 nan
我也试过用发电机
def id_generator(max_id):
curr = 1
while curr <= max_id:
yield curr
curr += 1
df['B'] = np.where(df['A'] < 0, next(id_generator(np.sum((df['A'] < 0).values.ravel()))), np.nan)
作为以前的解决方案,我得到了这个 dataframe
A B
0 -1 1
1 -1 1
2 1 nan
3 0 nan
4 -2 1
5 3 nan
6 0 nan
它似乎为它处理的每一行创建了一个迭代器/生成器,因此 id 始终为1
。 我发现的唯一一种解决方案是使用中间 dataframe
index = df[df['A'] < 0].index
new_df = pd.DataFrame(data=[x + 1 for x in range(len(index))], columns=['B'], index=index)
df = df.join(new_df)
所以我的问题是,有没有办法坚持使用np.where
解决方案而不是创建一个新的临时 dataframe? 或者是否有任何pandas
函数可以这样做?
使用DataFrame.loc
按range
获取可能的设置值:
m = df['A'] < 0
df.loc[m, 'B'] = range(1, m.sum() + 1)
print (df)
A B
0 -1 1.0
1 -1 2.0
2 1 NaN
3 0 NaN
4 -2 3.0
5 3 NaN
6 0 NaN
使用numpy.where
的解决方案:
m = df['A'] < 0
df['B'] = np.where(m, m.cumsum(), np.nan)
几乎任何事情都可以直接使用 numpy 和 pandas 函数来完成。 尽量避免使用迭代器和生成器
我有一个使用几行的解决方案
首先,为您的示例创建一个 dataframe:
import numpy as np
import pandas as pd
df = pd.DataFrame(data={'A': [-1,2,-1,0,-1,-1,2,3,5,-1]})
您可以使用 cumsum() 累积和来计算您遇到的负数数量并将其分配给新列
df['B'] = (df['A'] < 0).cumsum()
A B 0 -1 1 1 2 1 2 -1 2 3 0 2 4 -1 3 5 -1 4 6 2 4 7 3 4 8 5 4 9 -1 5
这仍然会在 A 列中有一个正数的值,因此您可以用 NaN 值替换这些值
df.loc[df['A'] >=0, 'B'] = np.NaN
你最终得到:
A B 0 -1 1.0 1 2 NaN 2 -1 2.0 3 0 NaN 4 -1 3.0 5 -1 4.0 6 2 NaN 7 3 NaN 8 5 NaN 9 -1 5.0
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.