【问题标题】:How to select rows of a Pandas dataframe that meet a condition and create new dataframes with the results如何选择满足条件的 Pandas 数据框行并使用结​​果创建新数据框
【发布时间】:2017-12-04 02:52:54
【问题描述】:

如何获取 Pandas DataFrame,根据条件对其进行拆分,并将生成的 DataFrames 保存为具有预先指定键的 dict 对象中的值?

我有一个 Pandas 数据框(来自 R's networkDynamicData 包的 hospital.dat_ 数据)。我将其读入并将其作为 Pandas DataFrame 处理,如下所示:

    with open('hospital.dat_', 'r') as f:
            data = f.readlines()

    #Convert to a pandas dataframe for easier manipulation

    split_data = []

    for line in data:
            split_line = line.split('\t')
            split_data.append(split_line)
    df = pd.DataFrame(split_data)

    df.columns=['Time', 'ID1', 'ID2', 'Att1', 'Att2'] #assign column names

DataFrame df 如下所示:

print df.head()

  Time   ID1   ID2 Att1   Att2
0  140  1157  1232  MED  ADM\n
1  160  1157  1191  MED  MED\n
2  500  1157  1159  MED  MED\n
3  520  1157  1159  MED  MED\n
4  560  1159  1191  MED  MED\n

我想根据TimeDataFrame 拆分为多个部分。作为 MWE,假设我想要一个具有三个 DataFrame 值的 dict 对象:

  • 一个包含Time小于200的条目的所有行;
  • 包含大于 200 但小于 550 的 Time 条目的所有行;
  • 包含大于 550 但小于 600 的 Time 条目的所有行(仅剩)
  • 开始的时间索引是关键。

也就是说,我想要:

0:

  Time   ID1   ID2 Att1   Att2
0  140  1157  1232  MED  ADM\n
1  160  1157  1191  MED  MED\n

200:

  Time   ID1   ID2 Att1   Att2
0  500  1157  1159  MED  MED\n
1  520  1157  1159  MED  MED\n

550:

  Time   ID1   ID2 Att1   Att2
0  560  1159  1191  MED  MED\n

我有一个列表,其中包含拆分值,末尾为 0,最大值为:

my_list = [0, 200, 550, 600]

作为开始,我已经尝试过:

   sorted_df = {i : [df.loc[(df['Time'] > i) & (df['Time'] <= j)] for i, j in enumerate(my_list)]}

但这只给了我一个键,因为我一直在覆盖,而且值是空列表。

问题:如何获取 Pandas DataFrame,根据条件对其进行拆分,并将生成的 DataFrames 保存为具有预先指定键的 dict 对象中的值?

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    您可以将cut 用于垃圾箱,然后将groupby 对象转换为dict

    df = pd.read_table('hospital.dat_')
    
    cat= pd.cut(df['Time'], bins=my_list, labels = my_list[:-1], include_lowest=True)
    print (cat)
    0      0
    1      0
    2    200
    3    200
    4    550
    Name: Time, dtype: category
    Categories (3, int64): [0 < 200 < 550]
    
    dfs = dict(tuple(df.groupby(cat)))
    print (dfs)
    {0:    Time   ID1   ID2 Att1 Att2
    0   140  1157  1232  MED  ADM
    1   160  1157  1191  MED  MED, 200:    Time   ID1   ID2 Att1 Att2
    2   500  1157  1159  MED  MED
    3   520  1157  1159  MED  MED, 550:    Time   ID1   ID2 Att1 Att2
    4   560  1159  1191  MED  MED}
    

    print (dfs[0])
       Time   ID1   ID2 Att1 Att2
    0   140  1157  1232  MED  ADM
    1   160  1157  1191  MED  MED
    
    print (dfs[200])
       Time   ID1   ID2 Att1 Att2
    2   500  1157  1159  MED  MED
    3   520  1157  1159  MED  MED
    

    也可以通过dict理解创建默认索引:

    dfs = {k:v.reset_index(drop=True) for k, v in df.groupby(cat)}
    print (dfs[0])
       Time   ID1   ID2 Att1 Att2
    0   140  1157  1232  MED  ADM
    1   160  1157  1191  MED  MED
    
    print (dfs[200])
       Time   ID1   ID2 Att1 Att2
    0   500  1157  1159  MED  MED
    1   520  1157  1159  MED  MED
    

    如果想要没有cut/groupby 的解决方案,您可以zip 没有最后一个列表的所有值以及没有第一个的所有值并使用dict comprehension

    zipped = zip(my_list[:-1], my_list[1:])
    print (list(zipped))
    [(0, 200), (200, 550), (550, 600)]
    
    sorted_df = {i : df.loc[(df['Time'] > i) & (df['Time'] <= j)].reset_index(drop=True) 
                     for i, j in zipped}
    print (sorted_df)
    {0:    Time   ID1   ID2 Att1 Att2
    0   140  1157  1232  MED  ADM
    1   160  1157  1191  MED  MED, 200:    Time   ID1   ID2 Att1 Att2
    0   500  1157  1159  MED  MED
    1   520  1157  1159  MED  MED, 550:    Time   ID1   ID2 Att1 Att2
    0   560  1159  1191  MED  MED}
    

    【讨论】:

    • 谢谢@jezrael,我最终使用了最后一个解决方案。如果其他人正在尝试此操作,请先将 Time 转换为数字,否则您将得到空列表。这有效:df['Time'] = df['Time'].apply(pd.to_numeric, errors='coerce')
    【解决方案2】:

    当您通过read_csv 创建数据框时,您应该能够通过它们的时间值直接访问这些行:

    df = pd.read_csv('hospital.dat_', delimiter='\t', index_col=['Time'])
    d1 = df[140:199]
    d2 = df[200:549]
    

    不过,我不确定这里需要的分隔符。

    【讨论】:

      猜你喜欢
      • 2020-03-02
      • 1970-01-01
      • 1970-01-01
      • 2020-02-07
      • 2018-10-06
      • 2023-02-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多