Python 在不覆盖非选定行的情况下,使用loc对数据帧进行选择性操作
我想应用算术运算来选择数据帧的行,选择取决于另一列 我首先尝试定义一个函数,并使用Python 在不覆盖非选定行的情况下,使用loc对数据帧进行选择性操作,python,pandas,dataframe,Python,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 #
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
假设我想将class==2的所有行的大小值平方,并将class==1的所有行的大小值立方
目标数据帧将是
# 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
非常感谢您的帮助。您需要使用
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
区分两种情况:
new_df['oper_size'] = np.where(new_df['class'] == 1,
new_df['size']**3,
new_df['size']**2)
new_df
您可以为
类
的每个值创建字典,以便可能用于新系列,然后仅使用**
的幂运算:
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
或某列,例如大小
:
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
你好,mcsoini,感谢您的回复-非常有帮助。
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