【问题标题】:How to read a csv with a malformed column of lists and plot the values如何读取包含格式错误的列表列的 csv 并绘制值
【发布时间】:2021-11-29 06:27:03
【问题描述】:

我有一个包含以下列的文件 csv

Customer List_Items
J.B.      [13,2,3,4,42,12]
F.C.      [1,44,51,24,12,53]
D.S.      NA 
B.V.      *
F.R.      [1,0,0,0,0,0]

我最多有六个项目。上面列表中的元素是频率。上面的元素是字符串,而不是列表,因为文件 csv 是在 python 编码之外手动创建的。 我想绘制一个多线图表,其中在 y 轴上我有频率,在 x 轴上标签 1、2、3、4、5、6。 要排除不在范围内的值,我可以过滤掉 NA 和 *.但我不知道如何在多线图中绘制列表。我应该在单独的列中展开列表吗?

例如: J.B. 将由一行表示

x-axis y-axis
1      13
2      2
3      3
4      4
5      42
6      12

其他客户也是如此。

【问题讨论】:

    标签: python pandas csv matplotlib plot


    【解决方案1】:
    • 可以使用以下方法将列从字符串转换回列表:
    • 在这种情况下需要有一个函数,它可以处理try-except 的错误
    • df.T.apply(pd.Series.explode).reset_index(drop=True) 用于将每个 list 中的值分隔为单独的行。
      • 这仅适用于每个list 的长度相同的情况,如示例所示。
      • 如果列表的长度不同,请改用以下行:
        • df = pd.concat([df.T[col].explode().reset_index(drop=True) for col in df.T.columns], axis=1)
    • 使用pandas.DataFrame.plot 绘制数据框。

    导入和加载数据帧

    import pandas as pd
    from ast import literal_eval  # convert string back to list
    import numpy as np
    
    # read the file
    df = pd.read_csv('data.csv', sep='\\s+', index_col=[0])
    
    # display(df)
                      List_Items
    Customer                    
    J.B.        [13,2,3,4,42,12]  ← this is a string
    F.C.      [1,44,51,24,12,53]
    D.S.                     NaN
    B.V.                       *
    F.R.           [1,0,0,0,0,0]
    

    功能

    # create a function with error handling to convert the column back to lists
    def test(row):
        try:
            row = literal_eval(row)  # convert the string to a list
        except (ValueError, SyntaxError):
            row = np.nan  # malformed rows are returned as NaN
        return row
    

    修复数据和绘图

    # apply the function to the row
    df.List_Items = df.List_Items.apply(lambda row: test(row))
    
    # drop nan
    df = df.dropna()
    
    # display(df)
                           List_Items
    Customer                         
    J.B.        [13, 2, 3, 4, 42, 12]  ← this is a list
    F.C.      [1, 44, 51, 24, 12, 53]
    F.R.           [1, 0, 0, 0, 0, 0]
    
    # transpose the dataframe and explode the list values to separate rows
    df = df.T.apply(pd.Series.explode).reset_index(drop=True)
    
    # display(df)
    Customer J.B. F.C. F.R.
    0          13    1    1
    1           2   44    0
    2           3   51    0
    3           4   24    0
    4          42   12    0
    5          12   53    0
    
    # plot
    ax = df.plot()
    

    【讨论】:

    • 非常感谢您的帮助和解释清楚的回答。这对我来说很有意义,而且效果很好。感谢您的时间和帮助特伦顿
    • @LdM 不客气。我很高兴这对你有用。
    猜你喜欢
    • 2014-01-14
    • 1970-01-01
    • 2017-12-04
    • 2016-10-25
    • 1970-01-01
    • 1970-01-01
    • 2018-04-28
    • 2021-12-03
    相关资源
    最近更新 更多