我有一个Pandas 数据框架,有三列, struct 如下:
Sample Start End
<string> <int> <int>
"开始"和"结束"中的值是较大字符串上的位置间隔(例如,从位置9000到11000).我的目标是将较大的字符串细分为10000个位置的窗口,并计算其中有多少个位置包含在数据帧的间隔中.
例如,窗口0:10000将包含1000个位置,窗口10000:20000将包含间隔9000:11000的其他1000个位置.
为此,我首先运行一个函数,将这些时间间隔拆分为多个窗口,这样,如果这是输入:
Sample Start End
A 2500 5000
A 9000 11000
A 18000 19500
这就是输出:
Sample Start End W_start W_end
A 2500 5000 0 10000
A 9000 10000 0 10000
A 10000 11000 10000 20000
A 18000 19500 10000 20000
这就是我使用的函数,其中df_sub
是数据帧的一行,w_size
是窗口大小(df_sub
00):
def split_into_windows(df_sub, w_size):
start, end = df_sub.Start, df_sub.End
w_start = start - (start % w_size)
w_end = w_start + w_size
if (w_start <= start <= w_end) and (w_start <= end <= w_end):
df_out = df_sub
elif (w_start <= start <= w_end) and (end > w_end):
out = []
df_tmp = df_sub.copy()
df_tmp.End = w_end
out.append(df_tmp.copy())
while (end > w_end):
w_start += w_size
w_end += w_size
df_tmp.Start = max(start, w_start)
df_tmp.End = min(end, w_end)
out.append(df_tmp.copy())
df_out = pd.DataFrame(out)
return df_out
我用apply()
调用函数:
df = df.apply(split_into_windows, axis=1, args=(w_size,))
但我有一个错误:
ValueError: Buffer has wrong number of dimensions (expected 1, got 2)
在网上我发现这个问题似乎与Pandas 合并有关,但我没有使用Pandas 合并.我认为这可能与以下事实有关:一些线路产生一个单一的输出序列,而另一些线路产生一个小的数据帧(分裂的数据帧).
请看这里:
Sample A
Start 6928
End 9422
Sample Start End
0 A 9939 10000
1 A 10000 11090
关于如何解决这个问题有什么建议吗?
要复制的最小数据集:https://file.io/iZ3fguCFlRbq
编辑#1:
我try 更改函数中的一行以获得一致的输出(即仅返回数据帧):
df_out = df_sub.to_frame().T
现在,apply()
轮"有效",如中所示,不会抛出错误,但输出如下所示:
0 Sample Start End
0 A 0 6915
1 Sample Start End
0 A 6928 9422
2 Sample Start End
0 A 9939 10000
...
<class 'pandas.core.series.Series'>
编辑#2:
我不能使用.iterrows()
,它需要太长的时间(估计数:周)和我操作的数据帧的大小.
编辑#3:
像这样使用multiprocessing
让我度过了这一天,但它仍然是一个次优的解决方案,相比之下,我可以实现一个正常运行的apply()
调用和一个并行应用程序,如pandarallel
或swifter
.仍在寻找任何提示:)
pool = mp.Pool(processes=48)
q = mp.Manager().Queue()
start = time.time()
for index, row in df_test.iterrows():
pool.apply_async(split_into_windows, args=(row, w_size, q))
pool.close()
pool.join()
out = []
while q.empty() == False:
out.append(q.get())
df = pd.DataFrame(out)