向量化 for 循环
Vectorizing for-loop
我有一个非常大的数据框(~10^8 行),我需要在其中更改一些值。我使用的算法很复杂,所以我试图将问题分解为下面的一个简单示例。我主要用 C++ 编程,所以我一直在思考 for 循环。我知道我应该矢量化,但我是 python 的新手,也是 pandas 的新手,无法提出更好的解决方案。欢迎任何提高性能的解决方案。
#!/usr/bin/python3
import numpy as np
import pandas as pd
data = {'eventID': [1, 1, 1, 2, 2, 3, 4, 5, 6, 6, 6, 6, 7, 8],
'types': [0, -1, -1, -1, 1, 0, 0, 0, -1, -1, -1, 1, -1, -1]
}
mydf = pd.DataFrame(data, columns=['eventID', 'types'])
print(mydf)
MyIntegerCodes = np.array([0, 1])
eventIDs = np.unique(mydf.eventID.values) # can be up to 10^8 values
for val in eventIDs:
currentTypes = mydf[mydf.eventID == val].types.values
if (0 in currentTypes) & ~(1 in currentTypes):
mydf.loc[mydf.eventID == val, 'types'] = 0
if ~(0 in currentTypes) & (1 in currentTypes):
mydf.loc[mydf.eventID == val, 'types'] = 1
print(mydf)
有什么想法吗?
编辑:我被要求解释我用 for 循环做了什么。
对于每个 eventID,我想知道所有对应类型是否包含 1 或 0 或两者。如果它们包含 1,则所有等于 -1 的值都应更改为 1。如果值为 0,则所有等于 -1 的值都应更改为 0。我的问题是独立地为每个 eventID 有效地执行此操作。每个 eventID 可以有一个或多个条目。
示例输入:
eventID types
0 1 0
1 1 -1
2 1 -1
3 2 -1
4 2 1
5 3 0
6 4 0
7 5 0
8 6 -1
9 6 -1
10 6 -1
11 6 1
12 7 -1
13 8 -1
示例输出:
eventID types
0 1 0
1 1 0
2 1 0
3 2 1
4 2 1
5 3 0
6 4 0
7 5 0
8 6 1
9 6 1
10 6 1
11 6 1
12 7 -1
13 8 -1
首先我们使用 Series.eq
then use DataFrame.groupby
on this mask and transform using any
, then using np.select
创建布尔掩码 m1
和 m2
根据条件 m1 or m2
:[=21= 从 1, 0
选择元素]
m1 = mydf['types'].eq(1).groupby(mydf['eventID']).transform('any')
m2 = mydf['types'].eq(0).groupby(mydf['eventID']).transform('any')
mydf['types'] = np.select([m1 , m2], [1, 0], mydf['types'])
结果:
# print(mydf)
eventID types
0 1 0
1 1 0
2 1 0
3 2 1
4 2 1
5 3 0
6 4 0
7 5 0
8 6 1
9 6 1
10 6 1
11 6 1
12 7 -1
13 8 -1
我有一个非常大的数据框(~10^8 行),我需要在其中更改一些值。我使用的算法很复杂,所以我试图将问题分解为下面的一个简单示例。我主要用 C++ 编程,所以我一直在思考 for 循环。我知道我应该矢量化,但我是 python 的新手,也是 pandas 的新手,无法提出更好的解决方案。欢迎任何提高性能的解决方案。
#!/usr/bin/python3
import numpy as np
import pandas as pd
data = {'eventID': [1, 1, 1, 2, 2, 3, 4, 5, 6, 6, 6, 6, 7, 8],
'types': [0, -1, -1, -1, 1, 0, 0, 0, -1, -1, -1, 1, -1, -1]
}
mydf = pd.DataFrame(data, columns=['eventID', 'types'])
print(mydf)
MyIntegerCodes = np.array([0, 1])
eventIDs = np.unique(mydf.eventID.values) # can be up to 10^8 values
for val in eventIDs:
currentTypes = mydf[mydf.eventID == val].types.values
if (0 in currentTypes) & ~(1 in currentTypes):
mydf.loc[mydf.eventID == val, 'types'] = 0
if ~(0 in currentTypes) & (1 in currentTypes):
mydf.loc[mydf.eventID == val, 'types'] = 1
print(mydf)
有什么想法吗?
编辑:我被要求解释我用 for 循环做了什么。 对于每个 eventID,我想知道所有对应类型是否包含 1 或 0 或两者。如果它们包含 1,则所有等于 -1 的值都应更改为 1。如果值为 0,则所有等于 -1 的值都应更改为 0。我的问题是独立地为每个 eventID 有效地执行此操作。每个 eventID 可以有一个或多个条目。
示例输入:
eventID types
0 1 0
1 1 -1
2 1 -1
3 2 -1
4 2 1
5 3 0
6 4 0
7 5 0
8 6 -1
9 6 -1
10 6 -1
11 6 1
12 7 -1
13 8 -1
示例输出:
eventID types
0 1 0
1 1 0
2 1 0
3 2 1
4 2 1
5 3 0
6 4 0
7 5 0
8 6 1
9 6 1
10 6 1
11 6 1
12 7 -1
13 8 -1
首先我们使用 Series.eq
then use DataFrame.groupby
on this mask and transform using any
, then using np.select
创建布尔掩码 m1
和 m2
根据条件 m1 or m2
:[=21= 从 1, 0
选择元素]
m1 = mydf['types'].eq(1).groupby(mydf['eventID']).transform('any')
m2 = mydf['types'].eq(0).groupby(mydf['eventID']).transform('any')
mydf['types'] = np.select([m1 , m2], [1, 0], mydf['types'])
结果:
# print(mydf)
eventID types
0 1 0
1 1 0
2 1 0
3 2 1
4 2 1
5 3 0
6 4 0
7 5 0
8 6 1
9 6 1
10 6 1
11 6 1
12 7 -1
13 8 -1