我想应用算术运算来选择Pandas DataFrame的行,选择取决于另一列。
我首先尝试定义一个函数并使用apply
来计算值,但这太慢了,因为我猜想每行都要评估函数逻辑。
使用loc
应用操作要快得多,但是当我连续应用此操作时,未选择的行每次都会被NaN覆盖。
一个说明性的例子是:
new_df = pd.DataFrame(
[[1, 0.1], [1, 0.2], [1, 0.3], [2, 0.4], [2, 0.5]], columns=["class", "size"]
)
new_df
# class size
# 1 0.1
# 1 0.2
# 1 0.3
# 2 0.4
# 2 0.5
说我想对类== 2的所有行的大小值求平方,并对类== 1的所有行将其值求立方。
目标DataFrame是
# class size oper_size
# 1 0.1 0.001
# 1 0.2 0.008
# 1 0.3 0.027
# 2 0.4 0.16
# 2 0.5 0.25
但是,如果我这样做:
new_df["oper_size"] = new_df["size"].loc[new_df["class"] == 1] ** 3
new_df["oper_size"] = new_df["size"].loc[new_df["class"] == 2] ** 2
然后得到的数据框是:
# class size oper_size
# 1 0.1 NaN
# 1 0.2 NaN
# 1 0.3 NaN
# 2 0.4 0.16
# 2 0.5 0.25
任何帮助都将不胜感激。
答案 0 :(得分:1)
您需要使用loc
选择要替换的行。例如
new_df.loc[new_df["class"] == 1, "oper_size"] = new_df[new_df["class"] == 1, "oper_size"] ** 3
或定义可用于两面的遮罩:
mask_1 = new_df["class"] == 1
new_df.loc[mask_1, "oper_size"] = new_df[mask_1, "oper_size"] ** 3
或者,您也可以使用numpy.where
来区分2种情况:
new_df['oper_size'] = np.where(new_df['class'] == 1,
new_df['size']**3,
new_df['size']**2)
new_df
class size oper_size
0 1 0.1 0.001
1 1 0.2 0.008
2 1 0.3 0.027
3 2 0.4 0.160
4 2 0.5 0.250
答案 1 :(得分:1)
您可以为class
的每个值创建字典,因此可以对新系列使用Series.map
,然后仅对**
使用幂运算:
new_df["oper_size"] = new_df["size"] ** new_df['class'].map({1:3, 2:2})
print (new_df)
class size oper_size
0 1 0.1 0.001
1 1 0.2 0.008
2 1 0.3 0.027
3 2 0.4 0.160
4 2 0.5 0.250
详细信息:
print (new_df['class'].map({1:3, 2:2}))
0 3
1 3
2 3
3 2
4 2
Name: class, dtype: int64
如果某些值不匹配,例如最后一行,则可以将所有值替换为某个数字,例如0
或某列,例如size
:
new_df = pd.DataFrame(
[[1, 0.1], [1, 0.2], [1, 0.3], [2, 0.4], [3, 0.5]], columns=["class", "size"]
)
new_df["oper_size1"]=(new_df["size"] ** new_df['class'].map({1:3, 2:2})).fillna(0)
new_df["oper_size2"]=(new_df["size"] ** new_df['class'].map({1:3, 2:2})).fillna(new_df["size"])
print (new_df)
class size oper_size1 oper_size2
0 1 0.1 0.001 0.001
1 1 0.2 0.008 0.008
2 1 0.3 0.027 0.027
3 2 0.4 0.160 0.160
4 3 0.5 0.000 0.500