【问题标题】:Iterating across multiple columns in Pandas DF and slicing dynamically遍历 Pandas DF 中的多个列并动态切片
【发布时间】:2017-01-15 15:40:09
【问题描述】:

TLDR:如何在不明确指定列或其值的情况下遍历 pandas 数据框中多列的所有选项?

加长版:我有一个看起来像这样的 pandas 数据框,只是它的功能或药物剂量组合比此处列出的要多得多。它可能有 70 种功能,而不是只有 3 种类型的功能......:

> dosage_df

First Score Last Score  A_dose  B_dose  C_dose
22          28          1       40      130
55          11          2       40      130
15          72          3       40      130
42          67          1       90      130
90          74          2       90      130
87          89          3       90      130
14          43          1       40      700
12          61          2       40      700
41          5           3       40      700

除了我的数据框,我还有一个 Python 字典,其中包含每个特征的相关范围。键是特征名称,它可以采用的不同值是键:

> dict_of_dose_ranges = {'A_dose': [1, 2, 3], 'B_dose': [40, 90], 'C_dose': [130,700]}

出于我的目的,我需要生成一个特定的组合(比如 A_dose = 1、B_dose = 90 和 C_dose = 700),并根据这些设置从我的数据框中取出相关切片,并从中进行相关计算较小的子集,并将结果保存在某处。

我需要为我的所有功能的所有可能组合执行此操作(远远超过这里的 3 个,并且将来会发生变化)。

在这种情况下,我可以轻松地将其弹​​出到 SkLearn 的参数网格中,生成选项:

> from sklearn.grid_search import ParameterGrid
> all_options = list(ParameterGrid(dict_of_dose_ranges)) 
> all_options

然后得到:

[{'A_dose': 1, 'B_dose': 40, 'C_dose': 130},
 {'A_dose': 1, 'B_dose': 40, 'C_dose': 700},
 {'A_dose': 1, 'B_dose': 90, 'C_dose': 130},
 {'A_dose': 1, 'B_dose': 90, 'C_dose': 700},
 {'A_dose': 2, 'B_dose': 40, 'C_dose': 130},
 {'A_dose': 2, 'B_dose': 40, 'C_dose': 700},
 {'A_dose': 2, 'B_dose': 90, 'C_dose': 130},
 {'A_dose': 2, 'B_dose': 90, 'C_dose': 700},
 {'A_dose': 3, 'B_dose': 40, 'C_dose': 130},
 {'A_dose': 3, 'B_dose': 40, 'C_dose': 700},
 {'A_dose': 3, 'B_dose': 90, 'C_dose': 130},
 {'A_dose': 3, 'B_dose': 90, 'C_dose': 700}]

这是我遇到问题的地方:

问题 #1) 我现在可以遍历 all_options,但我不知道现在如何从每个字典选项中选择我的 dosage_df(即 {'A_dose ': 1, 'B_dose': 40, 'C_dose': 130}) 没有明确地这样做。

过去,我可以这样做:

dosage_df[(dosage_df.A_dose == 1) & (dosage_df.B_dose == 40) & (dosage_df.C_dose == 130)]

First Score Last Score  A_dose  B_dose  C_dose
0           22          28      140     130

但现在我不确定要在括号内放什么来动态切片...

dosage_df[?????]

问题 #2) 当我实际输入具有各自范围的完整特征字典时,我收到一个错误,因为它认为它有太多选项...

from sklearn.grid_search import ParameterGrid
all_options = list(ParameterGrid(dictionary_of_features_and_ranges)) 
all_options

---------------------------------------------------------------------------
OverflowError                             Traceback (most recent call last)
<ipython-input-138-7b73d5e248f5> in <module>()
      1 from sklearn.grid_search import ParameterGrid
----> 2 all_options = list(ParameterGrid(dictionary_of_features_and_ranges))
      3 all_options

OverflowError: long int too large to convert to int

我尝试了许多替代方法,包括使用双 while 循环、tree / recursion method from here、另一个recursion method from here,但它没有结合在一起......非常感谢任何帮助。

【问题讨论】:

    标签: python pandas machine-learning scikit-learn grid-search


    【解决方案1】:

    您可以使用itertools.product 生成所有可能的剂量组合,并使用DataFrame.query 进行选择:

    from itertools import product
    
    for dosage_comb in product(*dict_of_dose_ranges.values()):
        dosage_items = zip(dict_of_dose_ranges.keys(), dosage_comb)
        query_str = ' & '.join('{} == {}'.format(*x) for x in dosage_items)
        sub_df = dosage_df.query(query_str)
    
        # Do Stuff...
    

    【讨论】:

      【解决方案2】:

      如何使用底层的 numpy 数组和一些布尔逻辑来构建一个只包含你想要的行的数组?

      dosage_df = pd.DataFrame((np.random.rand(40000,10)*100).astype(np.int))
      dict_of_dose_ranges={3:[10,11,12,13,15,20],4:[20,22,23,24]}
      
      #combined_doses will be bool array that will select all the lines that match the wanted combinations of doses
      
      combined_doses=np.ones(dosage_df.shape[0]).astype(np.bool)
      for item in dict_of_dose_ranges.items():
          #item[0] is the kind of dose
          #item[1] are the values of that kind of dose
      
          next_dose=np.zeros(dosage_df.shape[0]).astype(np.bool)
      
          #we then iterate over the wanted values
          for value in item[1]:
              # we select and "logical or" all lines matching the values
              next_dose|=(dosage_df[item[0]] == value)
          # we "logical and" all the kinds of dose
          combined_doses&=next_dose
      
      print(dosage_df[combined_doses])
      

      【讨论】:

      • 你能让这个工作吗?我收到一个错误:IndexError:只有整数、切片 (:)、省略号 (...)、numpy.newaxis (None) 和整数或布尔数组是有效的索引
      • 我已经编辑了一些代码以纠正错误arr[:,item[0]] 并用位运算符交换了算术并添加了示例值,以便它可以复制/粘贴。就目前而言,它对我来说运行良好。
      • 我认为它只对你有效 b/c dose_df 和 dict_of_dose_ranges 的列有整数键。
      • @Afflatus 我修复了它,它现在应该适用于所有列名。
      猜你喜欢
      • 2021-07-05
      • 2014-10-28
      • 1970-01-01
      • 1970-01-01
      • 2021-02-12
      • 2018-12-09
      • 1970-01-01
      • 2021-09-12
      • 1970-01-01
      相关资源
      最近更新 更多