【问题标题】:Pandas read csv using wild card pattern for selecting columnsPandas 使用通配符模式读取 csv 以选择列
【发布时间】:2021-01-07 06:31:31
【问题描述】:

我有 3 个 csv 文件

df = pd.DataFrame({'person_id': [11,11,11],'Age':[23,25,28],'Summary':['Test','Test1','Test2']})
df1 = pd.DataFrame({'person_id': [21,22,51],'Age':[26,29,22],'Order Summary':['Tep','Tst1','Tt2'],'Order Summary2':['ppp','Ttt','Tfsa']})
df2 = pd.DataFrame({'person_id': [31,31,41],'Age':[27,20,21],'Order Summary':['Tet','Tt1','Tt2'],'Order Summary1':['Tet','Tt1','Tt2']})

我想读取所有这些 csv 文件并创建一个数据框。

但是,我只想为每个文件读取两列,并且它们的名称有点不同。我想创建一个包含两列 person_idSummary 的最终数据框(在其他 csv 文件中也称为 Order Summary

我不想阅读其他 csv 文件的 AgeOrder Summary1Order Summary2 列。

在创建最终数据帧时,基本上只使用正则表达式/模式匹配来读取Summary|Order Summary

我在 SO 帖子中尝试了类似下面的内容

col_list = ["person_id", "Summary"]  # but here i don't know how to use regex
files = glob.glob("file*.csv")
dfs = [pd.read_csv(f,usecols = col_list, header=None, sep=";") for f in files]

meddata = pd.concat(dfs,ignore_index=True)

可以帮助我了解如何在阅读 csvs 时使用正则表达式来选择列吗?

我希望我的最终数据框具有如下所示的列,您可以看到每个 csv 文件中只有这 2 个必需的列是如何被选择和连接的)

Person_id   Summary
11           Test    
11           Test1
11           Test2
21           Tep
22           Tst1
51           Tt2 
31           Tet
31           Tt1
41           Tt2 

【问题讨论】:

  • 我只想要Order Summary。所有文件都有SummaryOrder Summary。我们不关心Order Summary 1Order Summary 2。如果你看到df1df2,你可以看到它有Order SummaryOrder Summary2。我只想要Order Summary。希望这个helos

标签: python python-3.x pandas dataframe glob


【解决方案1】:

阅读所有内容。您可以稍后通过检查它们是否在允许的列列表中来从每个 DF 中选择列,例如:

permitted = ['person_id', 'Summary', 'Order Summary']
df.loc[:, df.columns.isin(permitted)]
#   person_id Summary
#0         11    Test
#1         11   Test1
#2         11   Test2

【讨论】:

    【解决方案2】:

    更简单的方法是先重命名列 Order Summary,然后只选择预期的 2 列:

    dfs = [pd.read_csv(f, sep=";").rename(columns={'Order Summary':'Summary'})[['person_id','Summary']]
           for f in files] 
    

    旧答案:

    通过正则表达式使用DataFrame.filter 匹配person_idSummary 与字符串值的结尾:

    print (df.filter(regex='person_id|Summary$'))
       person_id Summary
    0         11    Test
    1         11   Test1
    2         11   Test2
    
    print (df1.filter(regex='person_id|Summary$'))
      person_id Order Summary
    0         21           Tep
    1         22          Tst1
    2         51           Tt2
    
    print (df2.filter(regex='person_id|Summary$'))
       person_id Order Summary
    0         31           Tet
    1         31           Tt1
    2         41           Tt2
    

    另一个想法是通过可能的值列表使用Index.intersection

    print (df[df.columns.intersection(['person_id', 'Summary', 'Order Summary'])])
    print (df1[df1.columns.intersection(['person_id', 'Summary', 'Order Summary'])])
    print (df2[df2.columns.intersection(['person_id', 'Summary', 'Order Summary'])])
     
            
    

    所以在您的解决方案中还要为输出 2 列 DataFrame 添加rename

    dfs = [pd.read_csv(f, sep=";").filter(regex='person_id|Summary$').rename(columns={'Order Summary':'Summary'})
           for f in files] 
    

    第二次需要:

    dfs = []       
    for f in files:
        df = pd.read_csv(f, sep=";")
        df1 = df[df.columns.intersection(['person_id', 'Summary', 'Order Summary'])].rename(columns={'Order Summary':'Summary'})
        dfs.append(df1)
    

    【讨论】:

    • 由于使用了过滤器,所以不需要usecols参数。对吗?
    • @TheGreat - 有 cvs 标头吗?
    • 是的。我的 csv 文件包含列名
    • @TheGreat - 你是对的,删除它。还有 header=None
    • 当我使用一个包含百万条记录的csv文件进行测试时,为什么df = [pd.read_csv(f, sep=";").filter(regex='person_id|Summary$') for f in files]这一行会产生df作为list类型?不应该是数据框类型吗?
    猜你喜欢
    • 2023-01-10
    • 2020-01-31
    • 1970-01-01
    • 2019-03-05
    • 2013-04-30
    • 2021-12-06
    • 1970-01-01
    • 2021-12-05
    • 1970-01-01
    相关资源
    最近更新 更多