使用 concat 函数处理 Python3 中的大型 CSV 文件
Handling large CSV files in Python3 using concat function
我正在尝试从 50 个 csv 文件中构建一个包含两列的数据框,这些文件有 5000 行和大约 15 列。当我在不使用 concat 函数的情况下尝试 运行 它时,它占用了大量内存并且出现了 kill 错误。现在我正在对数据库进行分块,然后将其连接起来。唯一的问题是,当我连接块时,它为每个块保留 header ,当我为 df 打印 head() 时,它只提供最后一个块的头行。有没有其他方法可以使我的代码 运行 更快,正如我读到的那样,在 for 循环中使用 concat 函数会使它变慢。我的代码是这样的:-
import os
import csv
import urllib.request as urllib
import datetime as dt
import pandas as pd
import pandas_datareader.data as web
import nsepy as nse
def saveNiftySymbols():
url = "https://www.nseindia.com/content/indices/ind_nifty50list.csv"
# pretend to be a chrome 47 browser on a windows 10 machine
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36"}
req = urllib.Request(url, headers = headers)
# open the url
x = urllib.urlopen(req)
sourceCode = x.read().decode('utf-8')
cr = csv.DictReader(sourceCode.splitlines())
l = [row['Symbol'] for row in cr]
return l
def symbolToPath(symbol, path='/Users/uditvashisht/Documents/udi_py/stocks/stock_dfs/'):
return os.path.join(path,"{}.csv".format(str(symbol)))
def combinedNifty(l):
mainDf=pd.DataFrame()
for symbol in l:
chunks=pd.read_csv(symbolToPath(symbol),chunksize=10,usecols=['Date','Close'],index_col='Date',parse_dates=True)
df=pd.DataFrame()
for chunk in chunks:
df=pd.concat([chunk])
df.rename(columns={'Close':symbol}, inplace=True)
if mainDf.empty:
mainDf = df
else:
mainDf = mainDf.join(df, how='outer')
print(mainDf.head())
mainDf.to_csv('combinedNifty.csv')
combinedNifty(saveNiftySymbols())
The only problem is that when I concat the chunks, it keeps the header
for each chunk and when I print head() for the df, it provides me the
head rows of only last chunk
这是因为实际发生的是你的 df 中只有最后一个块。当你 运行 这一行时:
df=pd.concat([chunk])
您实际上是在重新定义 df,仅将您的当前块与其他任何内容连接起来。它实际上就像你在做:
For chunk in chunks:
df = chunk
这就是为什么在调用 head() 方法时您只能看到最后一块。相反,您不需要 for 循环来连接块。 Concat 将数据帧列表作为参数并将它们连接在一起,因此您只需要做:
df = pd.concat(chunks)
这也应该提高性能,因为最好用一个包含许多数据帧的列表连接一次,而不是在 for 循环中执行类似 df = pd.concat([df, chunk]) 的操作,这是可能是您打算在原始代码中执行的操作。
我正在尝试从 50 个 csv 文件中构建一个包含两列的数据框,这些文件有 5000 行和大约 15 列。当我在不使用 concat 函数的情况下尝试 运行 它时,它占用了大量内存并且出现了 kill 错误。现在我正在对数据库进行分块,然后将其连接起来。唯一的问题是,当我连接块时,它为每个块保留 header ,当我为 df 打印 head() 时,它只提供最后一个块的头行。有没有其他方法可以使我的代码 运行 更快,正如我读到的那样,在 for 循环中使用 concat 函数会使它变慢。我的代码是这样的:-
import os
import csv
import urllib.request as urllib
import datetime as dt
import pandas as pd
import pandas_datareader.data as web
import nsepy as nse
def saveNiftySymbols():
url = "https://www.nseindia.com/content/indices/ind_nifty50list.csv"
# pretend to be a chrome 47 browser on a windows 10 machine
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.106 Safari/537.36"}
req = urllib.Request(url, headers = headers)
# open the url
x = urllib.urlopen(req)
sourceCode = x.read().decode('utf-8')
cr = csv.DictReader(sourceCode.splitlines())
l = [row['Symbol'] for row in cr]
return l
def symbolToPath(symbol, path='/Users/uditvashisht/Documents/udi_py/stocks/stock_dfs/'):
return os.path.join(path,"{}.csv".format(str(symbol)))
def combinedNifty(l):
mainDf=pd.DataFrame()
for symbol in l:
chunks=pd.read_csv(symbolToPath(symbol),chunksize=10,usecols=['Date','Close'],index_col='Date',parse_dates=True)
df=pd.DataFrame()
for chunk in chunks:
df=pd.concat([chunk])
df.rename(columns={'Close':symbol}, inplace=True)
if mainDf.empty:
mainDf = df
else:
mainDf = mainDf.join(df, how='outer')
print(mainDf.head())
mainDf.to_csv('combinedNifty.csv')
combinedNifty(saveNiftySymbols())
The only problem is that when I concat the chunks, it keeps the header for each chunk and when I print head() for the df, it provides me the head rows of only last chunk
这是因为实际发生的是你的 df 中只有最后一个块。当你 运行 这一行时:
df=pd.concat([chunk])
您实际上是在重新定义 df,仅将您的当前块与其他任何内容连接起来。它实际上就像你在做:
For chunk in chunks:
df = chunk
这就是为什么在调用 head() 方法时您只能看到最后一块。相反,您不需要 for 循环来连接块。 Concat 将数据帧列表作为参数并将它们连接在一起,因此您只需要做:
df = pd.concat(chunks)
这也应该提高性能,因为最好用一个包含许多数据帧的列表连接一次,而不是在 for 循环中执行类似 df = pd.concat([df, chunk]) 的操作,这是可能是您打算在原始代码中执行的操作。