【问题标题】:Split pandas dataframe in two if it has more than 10 rows如果熊猫数据框超过 10 行,则将其拆分为两部分
【发布时间】:2014-10-07 02:01:09
【问题描述】:

我有一个巨大的 CSV,其中包含许多行的许多表。如果每个数据帧包含超过 10 行,我想简单地将其拆分为 2。

如果为真,我希望第一个数据帧包含前 10 个数据帧,其余的包含在第二个数据帧中。

这有什么方便的功能吗?我环顾四周,但没有发现任何有用的...

split_dataframe(df, 2(if > 10))?

【问题讨论】:

  • 我正在构建一个 PowerPoint 幻灯片并将数据从 df 粘贴到每张幻灯片上的图表中,超过 10 行的图表变得不可读。

标签: python pandas split dataframe


【解决方案1】:

没有具体的便利功能。

您必须执行以下操作:

first_ten = pd.DataFrame()
rest = pd.DataFrame()

if df.shape[0] > 10: # len(df) > 10 would also work
    first_ten = df[:10]
    rest = df[10:]

【讨论】:

    【解决方案2】:

    如果满足条件,这将返回拆分的 DataFrame,否则返回原始和 None(然后您需要单独处理)。请注意,这假设每个 df 只需要拆分一次,并且拆分的第二部分(如果它超过 10 行(意味着原始数据超过 20 行))是可以的。

    df_new1, df_new2 = df[:10, :], df[10:, :] if len(df) > 10 else df, None
    

    请注意,您也可以根据需要使用df.head(10)df.tail(len(df) - 10) 来获取正面和背面。您还可以使用各种索引方法:如果需要,您可以只提供第一个维度索引,例如 df[:10] 而不是 df[:10, :](尽管我喜欢明确编码您所采用的维度)。您也可以使用df.ilocdf.ix 以类似的方式进行索引。

    但是,使用df.loc 时要小心,因为it is label-based and the input will never be interpreted as an integer position.loc 只会在您碰巧拥有从 0 开始且没有间隙的整数的索引标签时“意外”起作用。

    但您还应该考虑 pandas 提供的各种选项,用于将 DataFrame 的内容转储到 HTML 中,可能还包括 LaTeX,以便为演示文稿制作设计更好的表格(而不仅仅是复制和粘贴)。只需在 Google 上搜索如何将 DataFrame 转换为这些格式,就可以找到大量针对此应用程序的教程和建议。

    【讨论】:

    • df[:10] 工作正常,但是当我尝试 df[:10, :] 时出现此错误:TypeError: unhashable type
    • @LuisRamonRamirezRodriguez 这听起来像是与此问题无关的错误,您应该发布一个新问题并展示您正在使用的 DataFrame 是如何创建的以及其中的一些数据是什么样的。
    • @LuisRamonRamirezRodriguez:改用 df.loc[:10,:]
    • @nbeuchat 这实际上不是一个好建议。 loc 故意是一个基于 label 的索引,因此传递给它的内容是 never 解释为整数位置。如果您的索引标签恰好是从 0 开始的没有间隙的整数范围,这只会“意外地”起作用。相反,如果小心强制整数位置行为,最好使用iloc,也可能使用.ix。由于常规的 getitem 语法已经这样做了,这就是它没关系的原因。
    【解决方案3】:

    您可以在这里使用 DataFrame 的 head 和 tail 方法作为语法糖,而不是 slicing/loc。我使用 3 的拆分大小;对于您的示例,请使用 headSize=10

    def split(df, headSize) :
        hd = df.head(headSize)
        tl = df.tail(len(df)-headSize)
        return hd, tl
    
    df = pd.DataFrame({    'A':[2,4,6,8,10,2,4,6,8,10],
                           'B':[10,-10,0,20,-10,10,-10,0,20,-10],
                           'C':[4,12,8,0,0,4,12,8,0,0],
                          'D':[9,10,0,1,3,np.nan,np.nan,np.nan,np.nan,np.nan]})
    
    # Split dataframe into top 3 rows (first) and the rest (second)
    first, second = split(df, 3)
    

    【讨论】:

      【解决方案4】:

      如果您有一个大数据框并且需要分成可变数量的子数据框行,例如每个子数据框最多有 4500 行,此脚本可能会有所帮助:

      max_rows = 4500
      dataframes = []
      while len(df) > max_rows:
          top = df[:max_rows]
          dataframes.append(top)
          df = df[max_rows:]
      else:
          dataframes.append(df)
      

      然后您可以保存这些数据帧:

      for _, frame in enumerate(dataframes):
          frame.to_csv(str(_)+'.csv', index=False)
      

      希望这对某人有所帮助!

      【讨论】:

        【解决方案5】:

        一种基于np.split的方法:

        df = pd.DataFrame({    'A':[2,4,6,8,10,2,4,6,8,10],
                               'B':[10,-10,0,20,-10,10,-10,0,20,-10],
                               'C':[4,12,8,0,0,4,12,8,0,0],
                              'D':[9,10,0,1,3,np.nan,np.nan,np.nan,np.nan,np.nan]})
        
        listOfDfs = [df.loc[idx] for idx in np.split(df.index,5)]
        

        使用模数的小函数可以处理拆分不均匀的情况(例如np.split(df.index,4) 会抛出错误)。

        是的,我知道最初的问题比这更具体一些。但是,这应该回答标题中的问题。

        【讨论】:

          【解决方案6】:

          下面是一个简单的函数实现,它将 DataFrame 拆分为块和一些代码示例:

          import pandas as pd
          
          def split_dataframe_to_chunks(df, n):
              df_len = len(df)
              count = 0
              dfs = []
          
              while True:
                  if count > df_len-1:
                      break
          
                  start = count
                  count += n
                  #print("%s : %s" % (start, count))
                  dfs.append(df.iloc[start : count])
              return dfs
          
          
          # Create a DataFrame with 10 rows
          df = pd.DataFrame([i for i in range(10)])
          
          # Split the DataFrame to chunks of maximum size 2
          split_df_to_chunks_of_2 = split_dataframe_to_chunks(df, 2)
          print([len(i) for i in split_df_to_chunks_of_2])
          # prints: [2, 2, 2, 2, 2]
          
          # Split the DataFrame to chunks of maximum size 3
          split_df_to_chunks_of_3 = split_dataframe_to_chunks(df, 3)
          print([len(i) for i in split_df_to_chunks_of_3])
          # prints [3, 3, 3, 1]
          

          【讨论】:

            【解决方案7】:

            我使用 List Comprehension 将一个巨大的 DataFrame 切割成 100'000 个块:

            size = 100000
            list_of_dfs = [df.loc[i:i+size-1,:] for i in range(0, len(df),size)]
            

            或作为生成器:

            list_of_dfs = (df.loc[i:i+size-1,:] for i in range(0, len(df),size))
            

            【讨论】:

            • 我喜欢这个解决方案。但是,我认为您想要“df.iloc[i:i+size]”,否则您会在每个块中丢失一行,并且它也适用于非整数索引。
            • @ScottTalbert:不,这很好用,无需更改为 i+size。在 .loc 中,两者都是包容性的,不像列表的子集等
            • 单线.. 喜欢它!
            【解决方案8】:

            基于列表推导和groupby的方法,将所有拆分的数据帧存储在一个列表变量中,可以使用索引访问。

            例子:

            ans = [pd.DataFrame(y) for x, y in DF.groupby('column_name', as_index=False)]***
            ans[0]
            ans[0].column_name
            

            【讨论】:

              【解决方案9】:
              def split_and_save_df(df, name, size, output_dir):
                  """
                  Split a df and save each chunk in a different csv file.
              
                  Parameters:
                      df : pandas df to be splitted
                      name : name to give to the output file
                      size : chunk size
                      output_dir : directory where to write the divided df
                  """
                  import os
                  for i in range(0, df.shape[0],size):
                      start  = i
                      end    = min(i+size-1, df.shape[0]) 
                      subset = df.loc[start:end] 
                      output_path = os.path.join(output_dir,f"{name}_{start}_{end}.csv")
                      print(f"Going to write into {output_path}")
                      subset.to_csv(output_path)
                      output_size = os.stat(output_path).st_size
                      print(f"Wrote {output_size} bytes")
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2018-12-04
                • 2022-11-15
                • 1970-01-01
                • 2019-05-29
                • 2016-12-03
                • 1970-01-01
                相关资源
                最近更新 更多