python - Python/Pandas 中的快速数据帧规范化
问题描述
在 Python/Pandas 中,我正在尝试使用以下代码将数据帧的所有数字列标准化为每百万计数:
import pandas as pd
def normalize(df):
numerics = ['int16', 'int32', 'int64', 'float16', 'float32', 'float64']
numeric_cols = [col for col in df.columns if df[col].dtype in numerics]
sums = df.sum(axis=0, skipna = True)
for col in numeric_cols:
df.insert(df.columns.get_loc(col)+1, col+'_norm', ((df[col]/sums[col])*1000000)+1)
return df
dataset = pd.read_csv(csv_file, index_col=['Guide1', 'Guide2'], sep=',')
dataset = normalize(dataset)
这是一个简短的示例输入:
Guide1,Guide2,Gene1,Gene2,NHT1,NHT2,hart_essential_1,hart_essential_2,lib,RPE1_n1,RPE1_n2,RPE1_n3
Gene_1-KO-3,Non-Human-Target-150-KO-26,Gene_1,Non-Human-Target-150,False,True,False,False,12426.0,10634.0,8701.0,8084.0
Gene_2-KO-3,Non-Human-Target-150-KO-26,Gene_2,Non-Human-Target-150,False,True,False,False,12300.0,12383.0,6252.0,5388.0
Gene_1-KO-3,Gene_4-KO-2,Gene_1,Gene_4,False,False,False,False,11685.0,10006.0,10621.0,7002.0
Gene_1-KO-3,Gene_5-KO-2,Gene_1,Gene_5,False,False,False,False,11347.0,6726.0,3927.0,3943.0
Gene_1-KO-3,Gene_6-KO-1,Gene_1,Gene_6,False,False,False,False,11250.0,12469.0,3552.0,3334.0
该代码按预期工作并规范化该数据帧的所有数字列,但它似乎工作非常缓慢,也与其他规范化方法。我经常使用包含数百万行的数据框。对于大约 100 万行和只有 4 个数字列,在我的带有 Intel Core i7-6600U @ 2.6GHz 的移动计算机上进行归一化需要将近 10 分钟,尽管我预先计算了每一列的总和。有没有办法加快速度,例如并行化或一些巧妙的 Pandas 技巧?
非常感谢任何帮助和/或指示!
解决方案
感谢您花时间回答我!我想出了另一个我想分享的解决方案。YaoYao启发我测试多处理库来解决我的问题。以下解决方案运行得非常快。该脚本首先读取 .csv 文件,确定数字列的名称并计算它们的总和。然后它将数据集分成大小相等的块并将归一化函数映射到每个块。将生成的标准化数据帧串联起来以产生整个标准化数据集。
import pandas as pd
import math
import numpy as np
from multiprocessing import Pool
def index_marks(nrows, chunk_size):
return range(chunk_size, math.ceil(nrows / chunk_size) * chunk_size, chunk_size)
def split(dfm, chunk_size):
indices = index_marks(dfm.shape[0], chunk_size)
return np.split(dfm, indices)
def normalize(df, sums, numeric_cols):
for col in numeric_cols:
df.insert(df.columns.get_loc(col)+1, col+'_norm', ((df[col]/sums[col])*1000000)+1)
return df
def parallel_normalize(data):
df = data[0]
sums = data[1]
numeric_cols = data[2]
df = normalize(df, sums, numeric_cols)
return df
numerics = ['int16', 'int32', 'int64', 'float16', 'float32', 'float64']
dataset_file = '/path/to/file.csv'
cores = 3
dataset = pd.read_csv(dataset_file, index_col=['Guide1', 'Guide2'], sep=',')
dataset = dataset.fillna(0.0)
numeric_cols = [col for col in dataset.columns if dataset[col].dtype in numerics]
sums = dataset[numeric_cols].sum(axis=0, skipna = True)
chunks = split(dataset, int(round(dataset.shape[0]/cores)))
pool = Pool(cores)
dataset = pd.concat(pool.map(parallel_normalize, [[x, sums, numeric_cols] for x in chunks]))
pool.close()
pool.join()
不过,我不知道为什么加速如此之大。我原本预计可能会加速 60%,因为我将数据分成 3 个块。但它实际上是瞬间运行的。如果有人可以在这里发表评论并提供一些见解,我会非常高兴!
推荐阅读
- svg - 散景:保存的 svg 与 jupyter notebook 中显示的不同
- laravel - Laravel 模型属于关系加载问题
- javascript - Angular cli和javascript回调函数
- python - Anaconda Navigator 不更新软件包
- bash - 相邻的大括号扩展实际上是如何解析的?
- javascript - 具有数组的对象与数组的性能 - JavaScript
- python - pandas – 将函数逐行应用于 DataFrame,从而生成不同维度的新 DataFrame
- html - 纯文本版本与颜色切换器的可访问性
- c# - Xamarin android 应用程序已停止 / SIGSEGV 致命错误
- java - 将 Spring Boot .war 部署到 tomcat 时无法启动组件 [StandardEngine[Catalina]]