Pandas - 根据与另一列的交叉引用计算新值
Pandas - Calculate New Value Based on Cross Reference with Another Column
我正在尝试计算一个列中的新值,该列的值与另一列交叉引用。
>>> import pandas as pd
>>> df = pd.DataFrame( {"A":[0., 100., 80., 40., 0., 60.],
"B":[12, 12, 3, 19, 3, 19]} )
>>> df
A B
0 0.0 12
1 100.0 12
2 80.0 3
3 40.0 19
4 0.0 3
5 60.0 19
我想在 A 列中找到所有为 0 的值,在 B 列中找出相应的值,然后根据某个函数更改具有相同 B 值的所有 A 列值。例如,在上面的示例中,我想将 A 列的前两个值 df.A[0]
和 df.A[1]
分别从 0. 和 100. 更改为 0.5 和 99.5,因为 df.A[0]
是0. 并且它在 B 列中的值 df.B[0] = 12
与 df.B[1] = 12
.
相同
df
A B
0 0.5 12
1 99.5 12
2 79.5 3
3 40.0 19
4 0.5 3
5 60.0 19
我尝试链接 loc、aggregate、groupby 和 mask 功能,但没有成功。是通过 for 循环的唯一方法吗?
编辑:
扩大示例以更好地说明意图。
这会起作用:
import pandas as pd
df = pd.DataFrame( {"A":[0., 100., 40., 60.], "B":[12, 12, 19, 19]} )
def f(series):
return (series + 0.5).where(series == 0, series - 0.5)
B_value = df.loc[df['A'] == 0, 'B'][0]
df.loc[df['B'] == B_value, 'A'] = df.loc[df['B'] == B_value, 'A'].transform(f)
print(df)
输出:
A B
0 0.5 12
1 99.5 12
2 40.0 19
3 60.0 19
您可以将任意函数传递给 transform
。
可能有更简洁的方法来做到这一点;我觉得有点乱。
我找到了一个可行的解决方案,尽管可能不是最优的。我链接groupby,过滤和转换以获得所需的系列,然后将结果替换为原始数据帧。
import pandas as pd
df = pd.DataFrame( {"A":[0., 100., 80., 40., 0., 60.],
"B":[12, 12, 3, 19, 3, 19]} )
u = ( df.groupby(by="B", sort=False)
.filter(lambda x: x.A.min() == 0, dropna=False)
.A.transform( lambda x: (x+0.5).where(x == 0, x - 0.5) )
)
df.loc[pd.notnull(u), "A"] = u
给出以下结果
print("\ninitial df\n",df,"\n\nintermediate series\n",u,"\n\nfinal result",df)
initial df
A B
0 0.0 12
1 100.0 12
2 80.0 3
3 40.0 19
4 0.0 3
5 60.0 19
intermediate series
0 0.5
1 99.5
2 79.5
3 NaN
4 0.5
5 NaN
Name: A, dtype: float64
final result A B
0 0.5 12
1 99.5 12
2 79.5 3
3 40.0 19
4 0.5 3
5 60.0 19
我正在尝试计算一个列中的新值,该列的值与另一列交叉引用。
>>> import pandas as pd
>>> df = pd.DataFrame( {"A":[0., 100., 80., 40., 0., 60.],
"B":[12, 12, 3, 19, 3, 19]} )
>>> df
A B
0 0.0 12
1 100.0 12
2 80.0 3
3 40.0 19
4 0.0 3
5 60.0 19
我想在 A 列中找到所有为 0 的值,在 B 列中找出相应的值,然后根据某个函数更改具有相同 B 值的所有 A 列值。例如,在上面的示例中,我想将 A 列的前两个值 df.A[0]
和 df.A[1]
分别从 0. 和 100. 更改为 0.5 和 99.5,因为 df.A[0]
是0. 并且它在 B 列中的值 df.B[0] = 12
与 df.B[1] = 12
.
df
A B
0 0.5 12
1 99.5 12
2 79.5 3
3 40.0 19
4 0.5 3
5 60.0 19
我尝试链接 loc、aggregate、groupby 和 mask 功能,但没有成功。是通过 for 循环的唯一方法吗?
编辑: 扩大示例以更好地说明意图。
这会起作用:
import pandas as pd
df = pd.DataFrame( {"A":[0., 100., 40., 60.], "B":[12, 12, 19, 19]} )
def f(series):
return (series + 0.5).where(series == 0, series - 0.5)
B_value = df.loc[df['A'] == 0, 'B'][0]
df.loc[df['B'] == B_value, 'A'] = df.loc[df['B'] == B_value, 'A'].transform(f)
print(df)
输出:
A B
0 0.5 12
1 99.5 12
2 40.0 19
3 60.0 19
您可以将任意函数传递给 transform
。
可能有更简洁的方法来做到这一点;我觉得有点乱。
我找到了一个可行的解决方案,尽管可能不是最优的。我链接groupby,过滤和转换以获得所需的系列,然后将结果替换为原始数据帧。
import pandas as pd
df = pd.DataFrame( {"A":[0., 100., 80., 40., 0., 60.],
"B":[12, 12, 3, 19, 3, 19]} )
u = ( df.groupby(by="B", sort=False)
.filter(lambda x: x.A.min() == 0, dropna=False)
.A.transform( lambda x: (x+0.5).where(x == 0, x - 0.5) )
)
df.loc[pd.notnull(u), "A"] = u
给出以下结果
print("\ninitial df\n",df,"\n\nintermediate series\n",u,"\n\nfinal result",df)
initial df
A B
0 0.0 12
1 100.0 12
2 80.0 3
3 40.0 19
4 0.0 3
5 60.0 19
intermediate series
0 0.5
1 99.5
2 79.5
3 NaN
4 0.5
5 NaN
Name: A, dtype: float64
final result A B
0 0.5 12
1 99.5 12
2 79.5 3
3 40.0 19
4 0.5 3
5 60.0 19