【问题标题】:How to restructure data using a loop (without crashing computer!) and write to csv in python如何使用循环重构数据(不会导致计算机崩溃!)并在 python 中写入 csv
【发布时间】:2014-08-11 16:26:38
【问题描述】:

在 Pandas 中使用 read_csv, 我已经导入了一个超过 500K 行的庞大数据集,每一行都包含一个分类代码,其中包含来自特定日期和站点的位置和丰度值。随着时间的推移,这些值会针对不同的站点重复。我无法创建唯一的时间戳,因为没有记录时间,因此我只有日期。

我的栏目是:邮轮名称、站号、纬度、经度、日期(YY/MM/DD)、分类代码、丰度

我需要重新排列数据,以便我的列将是单独的分类代码 (n>400) 作为列名,并以丰度作为这些列的值,并且行将出现具有由位置和日期组成的唯一索引信息。更复杂的是,我需要在没有观察到这些特定样本的分类代码的情况下包含零


编辑:我创建了一个具有唯一标识符的新数据框,其中包括单个列中的所有相关位置信息、丰度和分类 ID,使用:
df['ID'] = df[['timestamp','cruise','station','lat','long','depth']].apply(lambda x: ','.join(map(str, x)), axis=1)
@ 987654322@

    ID  oldtxc  zoodns100
0   1977-02-13 00:00:00,MM7701,2,41.1833,-70.6667,...   101 114.95
1   1977-02-13 00:00:00,MM7701,2,41.1833,-70.6667,...   102 40118.18

使用 numpy unique 定义变量和计数
species = df3['TaxonomicCode']
cruise=df3['ID']
taxa=np.unique(species) #419
locats = np.unique(cruise) #27530

然后我创建了另一个用零填充的数据框:
aa=pd.DataFrame(index=locats, columns=taxa) #create empty matrix
aa=aa.fillna(0) #fill NaN with 0

2   100 101 102 103 104 105 106 107 108 ... 4500    4504    4601    4604    4700    5000    5100    5101    5150    9114
1977-02-13 00:00:00,MM7701,2,41.1833,-70.6667,33.0  0   0   0   0   0   0   0   0   0   0   ... 0   0   0   0   0   0   0   0   0   0

现在我想循环遍历原始数据以填充“aa”的值?

for d in range(len(df3)): loc1 = df3.ID[d] tax1 = df3.oldtxc[d] locIndex = np.where(locats == loc1)[0][0] taxIndex = np.where(taxa == tax1)[0][0] aa[locIndex, taxIndex] = df3.zoodns100[d]

这最初有效并给出了预期的输出,但仅在大约 1000 次迭代后使我的计算机崩溃(剩下 509K 次迭代...... gulp。)我正在使用 iPython notebook 和/或 spyder,结果是相同的。这可能是内存问题吗?

最终我需要将生成的数据帧“aa”打印到 CSV 文件中,有没有办法在迭代期间执行此操作以清除内存?


编辑 2

现在我看到我的循环导致列垂直连接到我的数据框“aa”上,这可以解释崩溃的原因。我正在尝试做的是从 510K 行长并包含丰度值的数据帧 ('df3') 中的单个列中填充 'aa' 的值(最终应该是 419 行 x 27530 列)对于每个位置的每个观察到的物种。对于“aa”的每一行,我需要将每个位置的所有丰度数据匹配到我各自的“aa”列中。 'aa' 的每一行都是一个唯一的位置索引,使用 'np.unique' 在 'df3' 510K -> 27K 唯一站的位置值上创建。

我正在尝试遍历长度“df3”并尝试在“df3”中找到匹配的位置索引(行),并将与这些索引关联的丰度数据与“aa”中相应的单行配对

(一清二楚对吧?这很难解释……)

我确定这是我的语法,但我想将值分配给数据框 'aa' aa[row, column] = value 这似乎导致连接,而不是分配值。我在这里错过了什么?

【问题讨论】:

    标签: python group-by pivot


    【解决方案1】:

    我无法理解您的整个问题,但我有几个建议可能会有所帮助。

    首先,我认为你的说法没有任何理由:

    aa=aa.fillna(0)
    

    预先分配所有这些零没有任何好处,而且会使您的代码混乱。

    我认为相反,你有一些类似的东西会更有效:

    aa=pd.DataFrame(index=locats, columns=taxa)
    for d in range(len(df3))
        ...
        #build a Series (new_row) for Just one row 
        ...
        aa = aa.append(new_row, ignore_index=True) #T/F depending on what you want
    

    另外,您可能需要重新考虑您的 for 循环。 Pandas 有一个 iterrows() 函数,您可以使用它。你可以这样使用它:

    for row_index, row in df3.iterrows(): 
    

    在连接时,您可能会引入新的性能问题。有一个帖子here 讨论了您的选择。但是如果你看,那些是在谈论数百万,而你的要少得多。所以我认为有希望。

    按照这些思路,不要觉得有义务在一次迭代中解决整个问题。这是不提前分配所有东西的另一个原因。如果您遇到真正的性能问题,则可以将其分成几块。例如,每迭代 1000 行,您可以将当前 DataFrame 刷新到 .csv 文件,从而释放该内存。您最终可能会得到 500 个 .csv 文件,但随后一个单独的函数将能够将它们全部读取。假设它们是目录中唯一的 .csv 文件:

    def concatinate_files(files_path):
        file_list= []
        for file_ in os.listdir(files_path):
            if file_.endswith('.csv'):
                file_list.append(files_path + '/' + file_)
       combined_df = DataFrame()
       for file_name in file_list:
            df = pd.read_csv(file_name)
           combined_df = combined_df.append(df, ignore_index=False)
    

    希望对您有所帮助。

    更新 8/20 以响应您的“edit2”

    您在最近的帖子中的问题是,如果“行”和“列”是整数,那么您尝试使用整数位置索引,但没有调用正确的函数 (iloc)。这会导致附加列。尝试运行此示例代码以了解我的意思。

    df = DataFrame(np.random.randn(4, 4))
    df['1','2']=3   #not what you want
    print df
    df.iloc[1,2]=3  #what I think you mean
    print df        
    

    不过,这又回到了我最初的建议。我认为预先分配 419x27530 不符合您的最佳利益。我认为您的一些问题来自您的心态/坚持尝试以这种方式适应事物。除了预分配,您提到您的数据方向是一个问题,但我不清楚这是怎么回事。将结果构建为 27530x1、27530x2 ... 27530x419 然后调用 DataFrame.Transpose (df.T) 以获得所需的 419x27530 方向是完全有效的。

    【讨论】:

    • 感谢您的帮助,但我仍在努力弄清楚如何解决这个问题。但是,我喜欢您将结果拆分的想法-我刚刚意识到原始唯一位置列表存在问题,并且我的代码不是从上到下而是在整个位置写入“aa”,因为排序错误在我的唯一 ID(“年”、“月”、“日”...但它按年排序,然后是“月”的第一个数字,因此 10 月在 1 月之前,写入 'aa 中的第 173 行' 作为第一个条目)。
    • 这些日期很容易排序。如果您考虑一下,对日期进行排序是一个非常普遍的问题。您无需重新发明轮子。您的时间戳列的“dtype”不是 numpy.datetime64 吗?如果是,那么排序将正常工作。一种方法是重新解析数据,如here 所述,如果您对数据有信心,一种更快的方法是使用DataFrame.astype 简单地更改数据类型
    • iloc 是诀窍,我很傻。我原来的循环现在可以在大约 10 分钟或更短的时间内运行。不幸的是,我没有看到任何其他方法。当我创建空数据框“aa”时,它已经用 NaN 填充,所以我只需用零替换它们,无论如何我都需要这些零来进行分析。我看不出这对时间有很大的影响。无论如何,一个障碍下来,还有更多。感谢您的意见和帮助。
    猜你喜欢
    • 2018-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多