我必须循环吗?有没有更快的方法来构建虚拟变量?
Do I had to loop? Is there a faster way to build dummy variables?
我有一些植物数据看起来像(但我最多有 7 个属性):
Unnamed: 0 plant att_1 att_2 ...
0 0 plant_a sunlover tall
1 1 plant_b waterlover sunlover
2 2 plant_c fast growing sunlover
我尝试使用 pandas get_dummies,例如:
df = pd.DataFrame({'A': ['a', 'b', 'a'], 'B': ['b', 'a', 'c'],'C': [1, 2, 3]})
pd.get_dummies(df, prefix=['col1', 'col2']):
.
C col1_a col1_b col2_a col2_b col2_c
0 1 1 0 0 1 0
1 2 0 1 1 0 0
2 3 1 0 0 0 1
但是sunlover在att_1或att_2中应该被编码为1。然后我将得到大约 30 个虚拟变量而不是 7 * 30 = 210 个变量。
我试图遍历整个集合并为每个虚拟对象添加值:
for count, plants in enumerate(data_plants.iterrows()):
print("First", count, plants)
for attribute in plants:
print("Second", count, attribute)
代码正在打印,因为我看到了代码浪费时间的问题。
这行得通,但速度不够快,无法用于 100k 或更多行。我想过使用 .value_counts() 来获取属性,然后访问数据帧虚拟变量以将其更新为 1,但随后我将覆盖该属性。此刻我有点迷失和想法。也许我必须使用其他软件包?
目标类似于:
Unnamed: 0 plant att_1 att_2 sunlover waterlover tall ...
0 0 plant_a sunlover tall 1 0 1
1 1 plant_b waterlover sunlover 1 1 0
2 2 plant_c fast growing sunlover 1 0 0
您只需要在某些方面与get_dummies相似,
但你应该以其他方式进行。
定义 df 的 viev,限于您的 "attribute" 列:
attCols = df[['att_1', 'att_2']]
在您的目标版本中,在此处添加其他 "attribute" 列。
然后定义一个包含唯一属性名称的索引:
colVals = pd.Index(np.sort(attCols.stack().unique()))
第三步定义一个函数,计算结果为
当前行:
def myDummies(row):
return pd.Series(colVals.isin(row).astype(int), index=colVals)
最后一步就是加入这个函数的应用结果
从 attCols:
的每一行
df = df.join(attCols.apply(myDummies, axis=1))
您的示例数据的结果是:
plant att_1 att_2 fast growing sunlover tall waterlover
0 plant_a sunlover tall 0 1 1 0
1 plant_b waterlover sunlover 0 1 0 1
2 plant_c fast growing sunlover 1 1 0 0
将 get_dummies
与 max
一起使用:
c = ['att_1', 'att_2']
df1 = df.join(pd.get_dummies(df[c], prefix='', prefix_sep='').max(axis=1, level=0))
print (df1)
plant att_1 att_2 fast growing sunlover waterlover tall
0 plant_a sunlover tall 0 1 0 1
1 plant_b waterlover sunlover 0 1 1 0
2 plant_c fast growing sunlover 1 1 0 0
3k
行的性能,在实际数据中应该不同:
df = pd.concat([df] * 1000, ignore_index=True)
In [339]: %%timeit
...:
...: c = ['att_1', 'att_2']
...: df1 = df.join(pd.get_dummies(df[c], prefix='', prefix_sep='').max(axis=1, level=0))
...:
...:
10.7 ms ± 1.11 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [340]: %%timeit
...: attCols = df[['att_1', 'att_2']]
...: colVals = pd.Index(np.sort(attCols.stack().unique()))
...: def myDummies(row):
...: return pd.Series(colVals.isin(row).astype(int), index=colVals)
...:
...: df1 = df.join(attCols.apply(myDummies, axis=1))
...:
...:
1.03 s ± 22 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
另一个解决方案:
In [133]: %%timeit
...: c = ['att_1', 'att_2']
...: df1 = (df.join(pd.DataFrame([dict.fromkeys(x, 1) for x in df[c].to_numpy()])
...: .fillna(0)
...: .astype(np.int8)))
...:
13.1 ms ± 723 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
我有一些植物数据看起来像(但我最多有 7 个属性):
Unnamed: 0 plant att_1 att_2 ...
0 0 plant_a sunlover tall
1 1 plant_b waterlover sunlover
2 2 plant_c fast growing sunlover
我尝试使用 pandas get_dummies,例如:
df = pd.DataFrame({'A': ['a', 'b', 'a'], 'B': ['b', 'a', 'c'],'C': [1, 2, 3]})
pd.get_dummies(df, prefix=['col1', 'col2']):
.
C col1_a col1_b col2_a col2_b col2_c
0 1 1 0 0 1 0
1 2 0 1 1 0 0
2 3 1 0 0 0 1
但是sunlover在att_1或att_2中应该被编码为1。然后我将得到大约 30 个虚拟变量而不是 7 * 30 = 210 个变量。 我试图遍历整个集合并为每个虚拟对象添加值:
for count, plants in enumerate(data_plants.iterrows()):
print("First", count, plants)
for attribute in plants:
print("Second", count, attribute)
代码正在打印,因为我看到了代码浪费时间的问题。 这行得通,但速度不够快,无法用于 100k 或更多行。我想过使用 .value_counts() 来获取属性,然后访问数据帧虚拟变量以将其更新为 1,但随后我将覆盖该属性。此刻我有点迷失和想法。也许我必须使用其他软件包?
目标类似于:
Unnamed: 0 plant att_1 att_2 sunlover waterlover tall ...
0 0 plant_a sunlover tall 1 0 1
1 1 plant_b waterlover sunlover 1 1 0
2 2 plant_c fast growing sunlover 1 0 0
您只需要在某些方面与get_dummies相似, 但你应该以其他方式进行。
定义 df 的 viev,限于您的 "attribute" 列:
attCols = df[['att_1', 'att_2']]
在您的目标版本中,在此处添加其他 "attribute" 列。
然后定义一个包含唯一属性名称的索引:
colVals = pd.Index(np.sort(attCols.stack().unique()))
第三步定义一个函数,计算结果为 当前行:
def myDummies(row):
return pd.Series(colVals.isin(row).astype(int), index=colVals)
最后一步就是加入这个函数的应用结果 从 attCols:
的每一行df = df.join(attCols.apply(myDummies, axis=1))
您的示例数据的结果是:
plant att_1 att_2 fast growing sunlover tall waterlover
0 plant_a sunlover tall 0 1 1 0
1 plant_b waterlover sunlover 0 1 0 1
2 plant_c fast growing sunlover 1 1 0 0
将 get_dummies
与 max
一起使用:
c = ['att_1', 'att_2']
df1 = df.join(pd.get_dummies(df[c], prefix='', prefix_sep='').max(axis=1, level=0))
print (df1)
plant att_1 att_2 fast growing sunlover waterlover tall
0 plant_a sunlover tall 0 1 0 1
1 plant_b waterlover sunlover 0 1 1 0
2 plant_c fast growing sunlover 1 1 0 0
3k
行的性能,在实际数据中应该不同:
df = pd.concat([df] * 1000, ignore_index=True)
In [339]: %%timeit
...:
...: c = ['att_1', 'att_2']
...: df1 = df.join(pd.get_dummies(df[c], prefix='', prefix_sep='').max(axis=1, level=0))
...:
...:
10.7 ms ± 1.11 ms per loop (mean ± std. dev. of 7 runs, 100 loops each)
In [340]: %%timeit
...: attCols = df[['att_1', 'att_2']]
...: colVals = pd.Index(np.sort(attCols.stack().unique()))
...: def myDummies(row):
...: return pd.Series(colVals.isin(row).astype(int), index=colVals)
...:
...: df1 = df.join(attCols.apply(myDummies, axis=1))
...:
...:
1.03 s ± 22 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
另一个解决方案:
In [133]: %%timeit
...: c = ['att_1', 'att_2']
...: df1 = (df.join(pd.DataFrame([dict.fromkeys(x, 1) for x in df[c].to_numpy()])
...: .fillna(0)
...: .astype(np.int8)))
...:
13.1 ms ± 723 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)