有没有更快的方法来根据条件更新数据框列值?
Is there a faster way to update dataframe column values based on conditions?
我正在尝试处理数据帧。这包括创建新列并根据其他列中的值更新它们的值。更具体地说,我有一个要分类的预定义 "source"。此来源可分为三个不同的类别 'source_dtp'、'source_dtot' 和 'source_cash'。我想向数据框添加三个新列,它们由基于原始 "source" 列的 1 或 0 组成。
我目前可以做到,只是真的很慢...
原始列示例:
source
_id
AV4MdG6Ihowv-SKBN_nB DTP
AV4Mc2vNhowv-SKBN_Rn Cash 1
AV4MeisikOpWpLdepWy6 DTP
AV4MeRh6howv-SKBOBOn Cash 1
AV4Mezwchowv-SKBOB_S DTOT
AV4MeB7yhowv-SKBOA5b DTP
期望的输出:
source_dtp source_dtot source_cash
_id
AV4MdG6Ihowv-SKBN_nB 1.0 0.0 0.0
AV4Mc2vNhowv-SKBN_Rn 0.0 0.0 1.0
AV4MeisikOpWpLdepWy6 1.0 0.0 0.0
AV4MeRh6howv-SKBOBOn 0.0 0.0 1.0
AV4Mezwchowv-SKBOB_S 0.0 1.0 0.0
AV4MeB7yhowv-SKBOA5b 1.0 0.0 0.0
这是我目前的方法,但速度很慢。我更喜欢这样做的矢量化形式,但我不知道如何 - 因为条件非常复杂。
# For 'source' we will use the following classes:
source_cats = ['source_dtp', 'source_dtot', 'source_cash']
# [0, 0, 0] would imply 'other', hence no need for a fourth category
# add new features to dataframe, initializing to nan
for cat in source_cats:
data[cat] = np.nan
for row in data.itertuples():
# create series to hold the result per row e.g. [1, 0, 0] for `cash`
cat = [0, 0, 0]
index = row[0]
# to string as some entries are numerical
source_type = str(data.loc[index, 'source']).lower()
if 'dtp' in source_type:
cat[0] = 1
if 'dtot' in source_type:
cat[1] = 1
if 'cash' in source_type:
cat[2] = 1
data.loc[index, source_cats] = cat
我正在使用 itertuples(),因为事实证明它比 interrows() 更快。
是否有更快的方法来实现与上述相同的功能?
编辑:这不仅仅是关于创建一个单一的热编码。它归结为根据另一列的值更新列值。例如。如果我有某个 location_id
我想更新它各自的 longitude
和 latitude
列 - 基于那个原始 id(没有像我上面那样迭代,因为它对于大型数据集)。
您可以使用 str.get_dummies
获取您的 OHEncodings。
c = df.source.str.get_dummies().add_prefix('source_').iloc[:, ::-1]
c.columns = c.columns.str.lower().str.split().str[0]
print(c)
source_dtp source_dtot source_cash
0 1 0 0
1 0 0 1
2 1 0 0
3 0 0 1
4 0 1 0
5 1 0 0
接下来,使用 pd.concat
连接 c
和 _id
。
df = pd.concat([df._id, c], 1)
print(df)
_id source_dtp source_dtot source_cash
0 AV4MdG6Ihowv-SKBN_nB 1 0 0
1 AV4Mc2vNhowv-SKBN_Rn 0 0 1
2 AV4MeisikOpWpLdepWy6 1 0 0
3 AV4MeRh6howv-SKBOBOn 0 0 1
4 AV4Mezwchowv-SKBOB_S 0 1 0
5 AV4MeB7yhowv-SKBOA5b 1 0 0
改进! 由于 Scott Boston 的 set_index
- reset_index
范例,现在稍微更流畅了:
df = df.set_index('_id')\
.source.str.get_dummies().iloc[:, ::-1]
df.columns = df.columns.str.lower().str.split().str[0]
df = df.add_prefix('source_').reset_index()
print(df)
_id source_dtp source_dtot source_cash
0 AV4MdG6Ihowv-SKBN_nB 1 0 0
1 AV4Mc2vNhowv-SKBN_Rn 0 0 1
2 AV4MeisikOpWpLdepWy6 1 0 0
3 AV4MeRh6howv-SKBOBOn 0 0 1
4 AV4Mezwchowv-SKBOB_S 0 1 0
5 AV4MeB7yhowv-SKBOA5b 1 0 0
另一种方法是在数据帧上使用 pd.get_dummies
。首先将'_id'放入索引。
source = source.set_index('_id')
df_out = pd.get_dummies(source).reset_index()
print(df_out)
输出:
_id source_Cash 1 source_DTOT source_DTP
0 AV4MdG6Ihowv-SKBN_nB 0 0 1
1 AV4Mc2vNhowv-SKBN_Rn 1 0 0
2 AV4MeisikOpWpLdepWy6 0 0 1
3 AV4MeRh6howv-SKBOBOn 1 0 0
4 AV4Mezwchowv-SKBOB_S 0 1 0
5 AV4MeB7yhowv-SKBOA5b 0 0 1
我正在尝试处理数据帧。这包括创建新列并根据其他列中的值更新它们的值。更具体地说,我有一个要分类的预定义 "source"。此来源可分为三个不同的类别 'source_dtp'、'source_dtot' 和 'source_cash'。我想向数据框添加三个新列,它们由基于原始 "source" 列的 1 或 0 组成。
我目前可以做到,只是真的很慢...
原始列示例:
source
_id
AV4MdG6Ihowv-SKBN_nB DTP
AV4Mc2vNhowv-SKBN_Rn Cash 1
AV4MeisikOpWpLdepWy6 DTP
AV4MeRh6howv-SKBOBOn Cash 1
AV4Mezwchowv-SKBOB_S DTOT
AV4MeB7yhowv-SKBOA5b DTP
期望的输出:
source_dtp source_dtot source_cash
_id
AV4MdG6Ihowv-SKBN_nB 1.0 0.0 0.0
AV4Mc2vNhowv-SKBN_Rn 0.0 0.0 1.0
AV4MeisikOpWpLdepWy6 1.0 0.0 0.0
AV4MeRh6howv-SKBOBOn 0.0 0.0 1.0
AV4Mezwchowv-SKBOB_S 0.0 1.0 0.0
AV4MeB7yhowv-SKBOA5b 1.0 0.0 0.0
这是我目前的方法,但速度很慢。我更喜欢这样做的矢量化形式,但我不知道如何 - 因为条件非常复杂。
# For 'source' we will use the following classes:
source_cats = ['source_dtp', 'source_dtot', 'source_cash']
# [0, 0, 0] would imply 'other', hence no need for a fourth category
# add new features to dataframe, initializing to nan
for cat in source_cats:
data[cat] = np.nan
for row in data.itertuples():
# create series to hold the result per row e.g. [1, 0, 0] for `cash`
cat = [0, 0, 0]
index = row[0]
# to string as some entries are numerical
source_type = str(data.loc[index, 'source']).lower()
if 'dtp' in source_type:
cat[0] = 1
if 'dtot' in source_type:
cat[1] = 1
if 'cash' in source_type:
cat[2] = 1
data.loc[index, source_cats] = cat
我正在使用 itertuples(),因为事实证明它比 interrows() 更快。
是否有更快的方法来实现与上述相同的功能?
编辑:这不仅仅是关于创建一个单一的热编码。它归结为根据另一列的值更新列值。例如。如果我有某个 location_id
我想更新它各自的 longitude
和 latitude
列 - 基于那个原始 id(没有像我上面那样迭代,因为它对于大型数据集)。
您可以使用 str.get_dummies
获取您的 OHEncodings。
c = df.source.str.get_dummies().add_prefix('source_').iloc[:, ::-1]
c.columns = c.columns.str.lower().str.split().str[0]
print(c)
source_dtp source_dtot source_cash
0 1 0 0
1 0 0 1
2 1 0 0
3 0 0 1
4 0 1 0
5 1 0 0
接下来,使用 pd.concat
连接 c
和 _id
。
df = pd.concat([df._id, c], 1)
print(df)
_id source_dtp source_dtot source_cash
0 AV4MdG6Ihowv-SKBN_nB 1 0 0
1 AV4Mc2vNhowv-SKBN_Rn 0 0 1
2 AV4MeisikOpWpLdepWy6 1 0 0
3 AV4MeRh6howv-SKBOBOn 0 0 1
4 AV4Mezwchowv-SKBOB_S 0 1 0
5 AV4MeB7yhowv-SKBOA5b 1 0 0
改进! 由于 Scott Boston 的 set_index
- reset_index
范例,现在稍微更流畅了:
df = df.set_index('_id')\
.source.str.get_dummies().iloc[:, ::-1]
df.columns = df.columns.str.lower().str.split().str[0]
df = df.add_prefix('source_').reset_index()
print(df)
_id source_dtp source_dtot source_cash
0 AV4MdG6Ihowv-SKBN_nB 1 0 0
1 AV4Mc2vNhowv-SKBN_Rn 0 0 1
2 AV4MeisikOpWpLdepWy6 1 0 0
3 AV4MeRh6howv-SKBOBOn 0 0 1
4 AV4Mezwchowv-SKBOB_S 0 1 0
5 AV4MeB7yhowv-SKBOA5b 1 0 0
另一种方法是在数据帧上使用 pd.get_dummies
。首先将'_id'放入索引。
source = source.set_index('_id')
df_out = pd.get_dummies(source).reset_index()
print(df_out)
输出:
_id source_Cash 1 source_DTOT source_DTP
0 AV4MdG6Ihowv-SKBN_nB 0 0 1
1 AV4Mc2vNhowv-SKBN_Rn 1 0 0
2 AV4MeisikOpWpLdepWy6 0 0 1
3 AV4MeRh6howv-SKBOBOn 1 0 0
4 AV4Mezwchowv-SKBOB_S 0 1 0
5 AV4MeB7yhowv-SKBOA5b 0 0 1