【发布时间】:2015-04-16 08:46:06
【问题描述】:
我试图在一个字符串中连接大量包含整数的列。
基本上,从:
df = pd.DataFrame({'id':[1,2,3,4],'a':[0,1,2,3], 'b':[4,5,6,7], 'c':[8,9,0,1]})
获得:
id join
0 1 481
1 2 592
2 3 603
3 4 714
方法一:
conc['glued']=''
i=1
while i < len(df.columns):
conc['glued'] = conc['glued'] + df[df.columns[i]].values.astype(str)
i=i+1
此方法有效,但有点长(在我的 18,000 行 x 40,000 列的“测试”案例中需要 45 分钟)。我担心列上的循环,因为这个程序应该在最后应用到 600.000 列的表上,我担心它会太长。
方法2a
conc['join']=[''.join(row) for row in df[df.columns[1:]].values.astype(str)]
方法2b
conc['apply'] = df[df.columns[1:]].apply(lambda x: ''.join(x.astype(str)), axis=1)
这两种方法的效率都是前一种方法的 10 倍,对行进行迭代非常好,并且在我的“调试”表 df 上完美运行。但是,当我将它应用于 18k x 40k 的“测试”表时,它会导致MemoryError:(在读取相应的 csv 文件后,我占用了 32GB RAM 的 60%)。
我可以在不超出内存的情况下复制我的 DataFrame,但奇怪的是,应用此方法会使代码崩溃。
您知道我可以如何修复和改进此代码以使用有效的基于行的迭代吗?谢谢!
附录: 这是我在测试用例中使用的代码:
geno_reader = pd.read_csv(genotype_file,header=0,compression='gzip', usecols=geno_columns_names)
fimpute_geno = pd.DataFrame({'SampID': geno_reader['SampID']})
我应该使用 chunksize 选项来读取这个文件,但我还没有真正理解如何在阅读后使用它。
方法一:
fimpute_geno['Calls'] = ''
for i in range(1,len(geno_reader.columns)):
fimpute_geno['Calls'] = fimpute_geno['Calls']\
+ geno_reader[geno_reader.columns[i]].values.astype(int).astype(str)
这项工作需要 45 分钟。
有一些非常恶心的代码,比如.astype(int).astype(str)。我不知道为什么 Python 不能识别我的整数并将它们视为浮点数。
方法二:
fimpute_geno['Calls'] = geno_reader[geno_reader.columns[1:]]\
.apply(lambda x: ''.join(x.astype(int).astype(str)), axis=1)
这导致MemoryError:
【问题讨论】:
-
你在做一些奇怪的事情:
fimpute_geno = pd.DataFrame({'SampID': geno_reader['SampID']})为什么要创建一个新的df?你能不能只做fimpute_geno = geno_reader['SampID']?或者你需要一份副本吗? dtype 是浮点数的原因可能是因为您缺少不能表示为 int 的数据NaN,您需要决定是替换这些值还是删除行,以及您要实现什么,看起来就像您正在尝试构建数据的字符串表示形式 -
我不使用
fimpute_geno = geno_reader['SampID'],因为这只会给我一个系列,或者我需要一个数据框来放置其他信息。我也怀疑有一些 NaN,但似乎没有。
标签: python-3.x pandas dataframe concatenation large-data