【问题标题】:Python function not working on Pandas Dataframe when subsetted in a loop在循环中子集化时,Python函数不适用于Pandas Dataframe
【发布时间】:2019-05-18 01:17:26
【问题描述】:

我创建了许多非常简单的函数,我想将它们应用于 pandas DataFrame。例如:

def dir_flag(start, end):
   try:
      if start < end:
         return '+'
      else:
         return '-'
   except:
      return 'NA'

我已将 csv 文件导入名为“mydata”的 DataFrame,并且可以应用我的功能:

mydata['direction'] = mydata.apply(lambda x: dir_flag(x['START_NODE'], x['END_NODE']), axis=1)

这很好用。但是,当我尝试将此功能或类似功能应用于作为“mydata”子集创建的 Pandas DataFrame 时,我收到以下错误:ValueError: Wrong number of items passed 2, placement implies 0。仅供参考mydata 包含一个 3 级多索引。

子集发生在以下循环中:

idx = pd.IndexSlice

idx1_levels = mydata.index.unique(level='idx_level1').tolist()

for x in idx1_levels:
   idx1_subset = mydata.loc[idx[x], ['START_NODE','END_NODE']]
   idx2_levels = idx1_subset.index.unique(level='idx_level2').tolist()
   for y in idx2_levels:

       idx2_subset = idx1_subset.loc[idx[y]]

       idx3_subset = idx2_subset.loc[idx[slice(None), 1.0], ['START_NODE','END_NODE']]

       idx3_subset['direction'] = journey_offset.apply(lambda a: dir_flag(a['START_NODE'], a['END_NODE']), axis=1)

似乎是idx3_subset = idx2_subset.loc[idx[slice(None), 1.0], ['START_NODE','END_NODE']] 语句导致了问题,因为我可以很高兴地将我的函数应用于idx2_subset

请注意,我对 Python 很陌生,我强烈怀疑有更好的方法可以对我的原始 DataFrame 进行子集化(例如,可能使用 groupby 方法)。我很高兴收到有关如何改进整体子集的建议 - 但请任何答案都可以解决为什么这不起作用的具体问题,因为这将有助于提高我对 Pandas DataFrames 如何工作的理解。

读入的 csv 的简化版本是:

idx_level1|idx_level2|idx_level3|idx_level4|START_NODE|END_NODE
353386066294006|1142|2018-09-20T07:57:26Z|1|18260004567689|18260005575180
353386066294006|1142|2018-09-20T07:57:26Z|2|18260004567689|18260004240718
353386066294006|1142|2018-09-20T07:57:26Z|3|18260005359901|18260004567689
353386066294006|1142|2018-09-20T07:57:31Z|1|18260004567689|18260005575180
353386066294006|1142|2018-09-20T07:57:31Z|2|18260004567689|18260004240718
353386066294006|1142|2018-09-20T07:57:31Z|3|18260005359901|18260004567689
353386066294006|1142|2018-09-20T07:57:36Z|1|18260004567689|18260005575180
353386066294006|1142|2018-09-20T07:57:36Z|2|18260004567689|18260004240718
353386066294006|1142|2018-09-20T07:57:36Z|3|18260005359901|18260004567689
353386066736543|22|2018-04-17T07:08:23Z|||
353386066736543|22|2018-04-17T07:08:24Z|||
353386066736543|22|2018-04-17T07:08:25Z|||
353386066736543|22|2018-04-17T07:08:26Z|||
353386066736543|403|2018-07-02T16:55:07Z|1|18260004580350|18260005235340
353386066736543|403|2018-07-02T16:55:07Z|2|18260005235340|18260005141535
353386066736543|403|2018-07-02T16:55:07Z|3|18260005235340|18260005945439
353386066736543|403|2018-07-02T16:55:07Z|4|18260006215338|18260005235340
353386066736543|403|2018-07-02T16:55:07Z|5|18260004483352|18260005945439
353386066736543|403|2018-07-02T16:55:07Z|6|18260004283163|18260006215338
353386066736543|403|2018-07-02T16:55:01Z|1|18260004580350|18260005235340
353386066736543|403|2018-07-02T16:55:01Z|2|18260005235340|18260005141535
353386066736543|403|2018-07-02T16:55:01Z|3|18260005235340|18260005945439
353386066736543|403|2018-07-02T16:55:01Z|4|18260006215338|18260005235340
353386066736543|403|2018-07-02T16:55:01Z|5|18260004483352|18260005945439
353386066736543|403|2018-07-02T16:55:01Z|6|18260004283163|18260006215338

我用来读入的代码如下:

mydata = pd.read_csv('/myloc/my_simple_data.txt', sep='|', 
 dtype={'idx_level1': 'int',
        'idx_level2': 'int',
        'idx_level3': 'str',
        'idx_level4': 'float',
        'START_NODE': 'str',
        'END_NODE': 'str'},
 parse_dates = ['idx_level3'],
 index_col=['idx_level1','idx_level2','idx_level3','idx_level4'])

有趣的是,将这个数据集放在一起 - 我意识到只有当我的数据中有空值时才会发生错误 - 注意这包括索引的一级中的空值。这里的索引合法地为空,即这不是数据中的错误。

【问题讨论】:

  • 您能提供一个数据框样本吗?确保您的错误在这里可以重现,并且那些试图帮助解决您的问题的人拥有所有必要的信息。
  • 嗨 Rahlf23,我已经编辑以包含一个示例数据集 - 这现在让我相信问题是由于索引的一级中的空值 - 但鉴于可能是这种情况,怎么能我规避了错误?
  • 嗨!您的示例代码不起作用,因为未定义 idx。但是,似乎确实必须有更好的方法来对数据框进行子集化。您能否告诉我您要选择哪个子集以及为什么?我想我们可以更好地帮助你
  • 另外,journey_offset 是什么?请确保您的数据和代码可在我们的空 Python 环境中编译和运行。见minimal reproducible example
  • 这是XY problem 的尖叫声。您应该尽量避免使用 Pandas 完全使用 for 循环。如果您通过minimal reproducible example 分享(可能在一个新问题中)您想要实现的目标,您更有可能找到一个好的解决方案。

标签: python pandas dataframe lambda slice


【解决方案1】:

所以问题源于在其中一个级别包含空值的多索引上执行索引切片。因此解决方案是用一个常量替换空值:

mydata = pd.read_csv('/myloc/my_simple_data.txt', sep='|', 
 dtype={'idx_level1': 'int',
        'idx_level2': 'int',
        'idx_level3': 'str',
        'idx_level4': 'float',
        'START_NODE': 'str',
        'END_NODE': 'str'},
 parse_dates = ['time']);

mydata.idx_level4 = mydata.idx_level4.fillna(1.0)

mydata.set_index(['idx_level1','idx_level2','idx_level3','idx_level4'], inplace=True)

虽然这确实回答了这个问题,但就了解具体导致错误的原因并给出避免它的方法而言 - 我仍然不知道为什么 null 会首先导致问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-05-16
    • 2018-07-09
    • 1970-01-01
    • 1970-01-01
    • 2018-10-13
    • 2017-04-01
    • 1970-01-01
    相关资源
    最近更新 更多