【问题标题】:read csv with column-name x value pairs使用列名 x 值对读取 csv
【发布时间】:2017-07-08 17:11:12
【问题描述】:

我有一个包含“列名 x 值”对的长 (csv) 文件,我想将其读入 pandas.DataFrame

user_id   col  val
00008901    1   55
00008901    2   66
00011501    1   77
00011501    3   88
00011501    4   99

结果应该是这样的:

             1   2    3   4
00008901    55  66    0   0
00011501    77   0   88  99

我试图将它读入一个列表并从中创建一个 DataFrame,但由于我有 450 万个元素,pandas 崩溃了。

最好的方法是什么?理想情况下直接使用 read_csv。

【问题讨论】:

    标签: csv pandas dictionary dataframe import


    【解决方案1】:

    我不认为可以使用read_csv 来解析 csv 文件。

    您可以创建字典等数据结构并使用它来创建数据框:

    import pandas as pd
    from collections import defaultdict
    import csv
    
    data_dict = defaultdict(lambda: [0] * columns)
    columns = 4
    delimiter = ','
    
    with open("my_csv.csv") as csv_file:
        reader = csv.DictReader(csv_file,delimiter=delimiter)
        for row in reader:
            row_id = row["user_id"]
            col = int(row["col"])-1
            val = int(row["val"])
            data_dict[row_id][col] = val
    
    df = pd.DataFrame(data_dict.values(), index=data_dict.keys(), columns=range(1, columns+1))
    

    对于包含以下内容的 csv 文件:

    user_id,col,val
    00008901,1,55
    00008901,2,66
    00011501,1,77
    00011501,3,88
    00011501,4,99
    

    输出是:

               1   2   3   4
    00008901  55  66   0   0
    00011501  77   0  88  99
    

    【讨论】:

      【解决方案2】:

      首先使用read_csv 创建DataFrame

       df = pd.to_csv('file.csv')
      

      然后需要set_indexunstack

      df1 = df.set_index(['user_id','col'])['val'].unstack(fill_value=0)
      print (df1)
      col       1   2   3   4
      user_id                
      8901     55  66   0   0
      11501    77   0  88  99
      

      使用pivot 的另一种解决方案,将NaN 替换为0fillna,最后转换为int

      df1 = df.pivot(index='user_id', columns='col', values='val').fillna(0).astype(int)
      print (df1)
      col       1   2   3   4
      user_id                
      8901     55  66   0   0
      11501    77   0  88  99
      

      如果出现错误:

      “ValueError:索引包含重复条目,无法重塑”

      这意味着你有一些重复,所以最快的解决方案是 groupbyunstack 和一些像 meansum 这样的聚合函数:

      print (df.groupby(['user_id','col'])['val'].mean().unstack(fill_value=0))
      col       1   2   3   4
      user_id                
      8901     55  66   0   0
      11501    77   0  88  99
      

      稍微改一下就好了csv:

      print (df)
         user_id  col  val
      0     8901    1   55
      1     8901    2   66
      2    11501    1   77 > duplicates -> 11501 and 1
      3    11501    1  151 > duplicates -> 11501 and 1
      4    11501    3   88
      5    11501    4   99
      
      
      print (df.groupby(['user_id','col'])['val'].mean().unstack(fill_value=0))
      col        1   2   3   4
      user_id                 
      8901      55  66   0   0
      11501    114   0  88  99
      

      其实我以为我没有重复,但发现我真的有一些...... 我不能使用“.mean”,因为它是分类值,但是通过首先查看排序表然后只保留最后一个条目来解决问题......然后应用(很棒!)解决方案..我仍然必须这样做完全理解;-)

      df.sort(columns=(['user_id','col']) ) # optional for debugging
      df.drop_duplicates(subset=['user_id','col'], keep='last', inplace=True)
      df_table = df.set_index(['user_id','col'])['val'].unstack(fill_value=0)
      

      【讨论】:

      • 哇,这已经是我好几天没有找到的很酷的方法了!问题是我在unstacking时出现错误>“ValueError:索引包含重复的条目,无法重塑”
      • 查看更新的解决方案,我尝试解释问题并获得解决方案。
      • 好几天都找不到的解决方案!非常感谢!
      • 谢谢,在旧版本的 pandas 中只有一个改进 df.sort(columns=(['user_id','col'])) 很好,在新版本中得到 FutureWarning: sort(columns=....) is deprecated, use sort_values(by=.....),所以最好使用 df.sort_values(['user_id','col'], inplace=True)
      • 不得不将 df = df[df.duplicated(keep='last')] 更改为 df = df.drop_duplicates(keep='last') 现在我再次收到错误,尽管它已删除相当多的重复。 “ValueError:索引包含重复的条目,无法重塑”......奇怪
      【解决方案3】:

      您无法使用 read_csv 直接读取所需的结构。但是您可以使用pivot_table 函数转换为所需的结构。

      df = pd.read_csv('filepath/your.csv')
      df = pd.pivot_table(df, index='user_id', columns='col', values='val, aggfunc='mean').reset_index()
      
      The output will be like
                   1   2    3   4
      00008901    55  66    0   0
      00011501    77   0   88  99
      

      【讨论】:

      • 看起来是个有趣的选择。就我而言,我不能使用“平均”,因为我有分类值,但只需要保留最后一个(见上文)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-10-05
      • 1970-01-01
      • 2012-12-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多