因此,对于一长串奇怪的数据处理问题中的另一个问题,我有一个数据框,如下所示:
id tof
0 10.0 2004847.0
1 10.0 2066116.0
2 10.0 5441996.0
3 10.0 5642443.0
4 15.0 1979815.0
5 15.0 1992399.0
6 15.0 2008208.0
7 15.0 2098060.0
8 15.0 3980280.0
9 27.0 2027878.0
10 27.0 2047992.0
11 27.0 5308106.0
12 27.0 6743403.0
,我想对数据进行门控,按ID分组。我只想保留数据,以使tof总和为一定范围的数字,而不同之处在于一定范围的数字之间。
例如,我将有tof_sum = [7000000,80000000]
,tof_dif = [3000000,3500000]
,门将保留行0 2,因为它们的总和在上面的数字之间,它们的差也是如此。由于与第2行的关系,它还将保留第1行。但是,不会保留ID为15的任何行,因为没有两行的总和超过7000000。
我可以想象设置
a = pd.DataFrame([[k, c0, c1] for k, tof in Da.groupby('id').tof
for c0, c1 in combinations(tof, 2)
], columns=['id', 'tof0', 'tof1'])
会为每个id成对生成所有组合,然后像这样对它们进行补偿:
id tof0 tof1
0 10.0 2004847.0 2066116.0 (sum not bigger than 7000000, next)
1 10.0 2004847.0 5441996.0 (this sum is in range, difference is in range, ✓)
2 10.0 2004847.0 5642443.0 (sum and difference are in range here too, ✓ )
3 10.0 2066116.0 5441996.0 (etc, etc)
4 10.0 2066116.0 5642443.0
5 10.0 5441996.0 5642443.0
6 15.0 1979815.0 1992399.0
7 15.0 1979815.0 2008208.0
8 15.0 1979815.0 2098060.0
9 15.0 1979815.0 3980280.0
10 15.0 1992399.0 2008208.0
11 15.0 1992399.0 2098060.0
12 15.0 1992399.0 3980280.0
13 15.0 2008208.0 2098060.0
14 15.0 2008208.0 3980280.0
15 15.0 2098060.0 3980280.0
16 27.0 2027878.0 2047992.0
17 27.0 2027878.0 5308106.0
18 27.0 2027878.0 6743403.0
19 27.0 2047992.0 5308106.0
20 27.0 2047992.0 6743403.0
21 27.0 5308106.0 6743403.0
并且每次满足求和和差的条件都在各自的范围内时,它将保存带有tof的行。
但是对于要使用的数百万行数据数据文件,此命令花费了惊人的时间(例如数分钟)。
有什么想法吗?
答案 0 :(得分:1)
如评论中所述,处理几分钟的数百万行数据不是很长时间。您可以通过广播对过程进行矢量化处理:
def get_pairs(g):
x = g.tof.values
# upper triangle matrix to avoid duplicate pairs: (a,b) and (b,a)
uniques = np.arange(len(x)) > np.arange(len(x))[:, None]
sums = x + x[:, None]
sum_mask = (sums>7000000) & (sums<80000000)
diffs = np.abs(x - x[:, None])
diff_mask = (diffs > 3000000) & (diffs < 3500000)
mask = sum_mask & diff_mask & uniques
ret_df = pd.DataFrame(mask, index=x, columns=x)
ret_df = ret_df.stack()
return ret_df[ret_df]
然后
new_df = df.groupby('id').apply(get_pairs).reset_index().drop(0, axis=1)
输出:
id level_1 level_2
0 10.0 2004847.0 5441996.0
1 10.0 2066116.0 5441996.0
2 27.0 2027878.0 5308106.0
3 27.0 2047992.0 5308106.0
稍作修改即可为您提供行的索引,您可以使用它们来过滤原始数据:
def get_pairs(g):
x = g.tof.values
# upper triangle matrix
uniques = np.arange(len(x)) > np.arange(len(x))[:, None]
sums = x + x[:, None]
sum_mask = (sums>7000000) & (sums<80000000)
diffs = np.abs(x - x[:, None])
diff_mask = (diffs > 3000000) & (diffs < 3500000)
mask = sum_mask & diff_mask & uniques
# note the different columns and index.
ret_df = pd.DataFrame(mask, index=g.index, columns=g.index)
ret_df = ret_df.stack()
return ret_df[ret_df]
输出:
id level_1 level_2
0 10.0 0 2
1 10.0 1 2
2 27.0 9 11
3 27.0 10 11