我有一个大文件(19GB左右),我想在内存中加载以执行某些列的聚合。
文件如下所示:
id, col1, col2, col3,
1 , 12 , 15 , 13
2 , 18 , 15 , 13
3 , 14 , 15 , 13
3 , 14 , 185 , 213
请注意,我在加载到数据框后使用了列(id,col1)进行聚合,还要注意这些键可能会连续重复几次,例如:
3 , 14 , 15 , 13
3 , 14 , 185 , 213
对于小文件,以下脚本可以执行此任务
import pandas as pd
data = pd.read_csv("data_file", delimiter=",")
data = data.reset_index(drop=True).groupby(["id","col1"], as_index=False).sum()
但是,对于大文件,我需要在读取csv文件时使用chunksize来限制加载到内存中的行数:
import pandas as pd
data = pd.read_csv("data_file", delimiter=",", chunksize=1000000)
data = data.reset_index(drop=True).groupby(["id","col1"], as_index=False).sum()
在后一种情况下,如果(id,col1)相似的行被分成不同的文件,则会出现问题。我该怎么处理?
修改
正如@EdChum所指出的那样,有一个潜在的解决方法,就是不仅仅是将groupby结果附加到一个新的csv并重新读取并再次执行聚合,直到df大小没有。改变。
然而,这是最糟糕的情况,未处理,即:
当所有文件(或者内存中无法处理的足够多的文件)在结尾处具有相同的问题类似(id,col1)时。这将导致系统返回MemoryError
答案 0 :(得分:8)
Dask.dataframe几乎可以不加修改地执行此操作
$ cat so.csv
id,col1,col2,col3
1,13,15,14
1,13,15,14
1,12,15,13
2,18,15,13
2,18,15,13
2,18,15,13
2,18,15,13
2,18,15,13
2,18,15,13
3,14,15,13
3,14,15,13
3,14,185,213
$ pip install dask[dataframe]
$ ipython
In [1]: import dask.dataframe as dd
In [2]: df = dd.read_csv('so.csv', sep=',')
In [3]: df.head()
Out[3]:
id col1 col2 col3
0 1 13 15 14
1 1 13 15 14
2 1 12 15 13
3 2 18 15 13
4 2 18 15 13
In [4]: df.groupby(['id', 'col1']).sum().compute()
Out[4]:
col2 col3
id col1
1 12 15 13
13 30 28
2 18 90 78
3 14 215 239
虽然没有人为groupby写过as_index=False
。我们可以使用assign
解决此问题。
In [5]: df.assign(id_2=df.id, col1_2=df.col1).groupby(['id_2', 'col1_2']).sum().compute()
Out[5]:
id col1 col2 col3
id_2 col1_2
1 12 1 12 15 13
13 2 26 30 28
2 18 12 108 90 78
3 14 9 42 215 239
我们会像你的第一个例子一样抽出大块并做组。一旦我们对每个块进行分组和求和,我们就会将所有中间结果收集在一起并执行另一个稍微不同的groupby.sum
。这假设中间结果将适合内存。
作为一个令人愉快的副作用,它也将同时运作。
答案 1 :(得分:1)
首先,您可以通过usecols - Dim Filter1 = "filterword1"
Dim Filter2 = "filterword2"
TextBox1.Text = WebBrowser1.DocumentText
TextBox2.Text = WebBrowser1.DocumentText
Dim lines As New List(Of String)
lines = TextBox1.Lines.ToList
For i As Integer = lines.Count - 1 To 0 Step -1
If Not Regex.IsMatch(lines(i), Filter1) Then
lines.RemoveAt(i)
End If
Next
TextBox1.Lines = lines.ToArray
Dim lines1 As New List(Of String)
lines1 = TextBox3.Lines.ToList
For i As Integer = lines1.Count - 1 To 0 Step -1
If Not Regex.IsMatch(lines1(i), Filter2) Then
lines1.RemoveAt(i)
End If
Next
TextBox1.Lines = lines1.ToArray
读取csv来选择唯一常量列表。然后通过块读取csv,通过id和groupby的子集读取concat块。 better explain
如果使用列usecols=['id', 'col1']
更好,请更改col1
。这取决于您的数据。
或者您只能阅读一列constants = df['col1'].unique().tolist()
,这取决于您的数据。
df = pd.read_csv(io.StringIO(temp), sep=",", usecols=['id'])