在 python 中,使用 lambda 将空列表添加到数据框列会引发 valueError

Posted

技术标签:

【中文标题】在 python 中,使用 lambda 将空列表添加到数据框列会引发 valueError【英文标题】:In python adding empty list to dataframe column by using lambda raises valueError 【发布时间】:2019-01-03 10:15:54 【问题描述】:

我能够在合成数据上重现错误:

import pandas as pd
from datetime import datetime

df1 = pd.DataFrame('A': ['A0', 'A1', 'A2', 'A3'],
                    'B': ['B0', 'B1', 'B2', 'B3'],
                    'C': [datetime.now(), datetime.now(), datetime.now(), datetime.now()],
                    'D': ['D0', 'D1', 'D2', 'D3'],
                   index=[0, 1, 2, 3]);
df2 = pd.DataFrame('A': ['A1', 'A2', 'A3', 'A4'],
                    'E': ['E1', 'E2', 'E3', 'E4'],
                   index=[0,1,2,3]);

df = pd.merge(df1, df2, how='left', on=['A', 'A']);

def getList(row):
    r = [];
    if row["A"] == "A1": r.append("test-01");
    if row["B"] == "B1": r.append("test-02");
    if row["B"] == "B2": r.append("test-03");
    return r;

df["NEW_COLUMN"] = df.apply(lambda row: getList(row), axis = 1);

原帖:我想根据多个条件在 pandas 数据框中创建一个新列。新列的值应该是列表。但是我得到“ValueError:指定索引传递的空数据。”如果列表为空。

def getList(p_row):
  r = [];
  if p_row["field1"] > 0: r.append("x");
  ...
  return r;

df["new_list_field"] = df.apply(lambda row: getList(row), axis = 1);

完整的错误:

ValueError Traceback(最近一次调用最后一次) C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\internals.py 在 create_block_manager_from_arrays(数组,名称,轴)4636尝试: -> 4637 blocks = form_blocks(arrays, names, axes) 4638 mgr = BlockManager(blocks, axes)

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\internals.py 在 form_blocks(数组,名称,轴)4728如果len(object_items)> 0: -> 4729 object_blocks = _simple_blockify(object_items, np.object_) 4730 blocks.extend(object_blocks)

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\internals.py 在 _simple_blockify(元组,dtype)4758“”“ -> 4759 个值,位置 = _stack_arrays(tuples, dtype) 4760

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\internals.py 在 _stack_arrays(tuples, dtype) 4822 for i, arr in enumerate(arrays): -> 4823 堆叠[i] = _asarray_compat(arr) 4824

ValueError: 无法将输入数组从形状 (2) 广播到形状 (195)

在处理上述异常的过程中,又发生了一个异常:

ValueError Traceback(最近一次调用最后一次) 在 () ----> 1 df["new_list_field"] = df.apply(lambda row: getList(row), axis = 1);

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\frame.py 在 应用(自我,功能,轴,广播,原始,减少,参数,**kwds)4875 f,轴,4876减少=减少, -> 4877 ignore_failures=ignore_failures) 4878 else: 4879 返回 self._apply_broadcast(f, 轴)

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\frame.py 在 _apply_standard(self,func,axis,ignore_failures,reduce)4988索引=无4989 -> 4990 结果 = self._constructor(data=results, index=index) 4991 result.columns = res_index 4992

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\frame.py 在 init(self、data、index、columns、dtype、copy) 第328章 第329章 --> 330 mgr = self._init_dict(数据、索引、列、dtype=dtype) 第331章 332 将 numpy.ma.mrecords 导入为 mrecords

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\frame.py 在 _init_dict(自我,数据,索引,列,dtype) 459 个数组 = [data[k] for k in keys] 460 --> 461 return _arrays_to_mgr(arrays, data_names, index, columns, dtype=dtype) 462 463 def _init_ndarray(self, values, index, columns, dtype=None, copy=False):

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\frame.py 在 _arrays_to_mgr(数组,arr_names,索引,列,dtype)6171轴= [_ensure_index(列),_ensure_index(索引)] 6172 -> 6173 return create_block_manager_from_arrays(arrays, arr_names, axes) 6174 6175

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\internals.py 在 create_block_manager_from_arrays(数组、名称、轴)4640 返回经理 4641 除了 ValueError 作为 e: -> 4642 construction_error(len(arrays), arrays[0].shape, axes, e) 4643 4644

C:\ProgramData\Anaconda3\lib\site-packages\pandas\core\internals.py 在 施工错误(tot_items,block_shape,轴,e)4604 如果 block_shape[0] == 0,则提高 e 4605: -> 4606 raise ValueError("指定索引传递的空数据。")

4607 raise ValueError("传递值的形状是 0,索引 暗示 1".format( 4608 已通过,暗示))

ValueError:指定索引传递的空数据。

【问题讨论】:

欢迎来到 SO!,您能否以 Minimal, Complete, and Verifiable 的方式提供 dataframe 很遗憾无法共享原始数据。它是由多个数据源合并而成的一百万条记录数据集,包含非常敏感的信息。在 2 列上有索引。不幸的是,无法使用示例数据重现它,因为该代码可以正常工作。还尝试创建大型数据集切片的副本,但收到相同的错误消息。 数据来自 rdbms 通过 odbc,也来自 csv 文件。用 copy() 做了一小块,只保留了几个字段。 ID int64 PAYMENT_ID float64 CREDIT_FL object TRX_MSG object CALENDAR_DATE datetime64[ns] dtype: object 对象类型字段应该是字符串。使用 CALENDAR_DATE 字段会引发 ValueError Traceback(最近一次调用最后一次)。没有这些字段,它就可以工作。尽管我已经可以使用简单的条件以及 int 和 string 类型创建几个字段,但数据类型可能有问题。 一个真诚的建议:你能尽量不要在python脚本中使用分号吗?他们不会在 Python 中做任何事情,不会抛出错误,而是让代码更笨拙...... 【参考方案1】:

最终制作了一个列表列表,将其转换为pd.Series() 并将其分配给一个新列。字典 key2list 将可变长度列表作为值返回:

new_col_list = []

for _, row in my_df.iterrows():
    new_col_list.append(key2list[row[u'key']])

my_df[u'new_col'] = pd.Series(new_col_list)

【讨论】:

【参考方案2】:

此函数的输出长度因行而异,但您不能将长度不等的列表分配给新的 pandas 列。您可以通过以下方式进行验证:

for idx,row in df.iterrows():
    print(getList(row))

另一种方法是将输出转换为字符串:

def getListString(row):
    r = ''
    if row["A"] == "A1": r+="test-01"
    if row["B"] == "B1": r+="test-02"
    if row["B"] == "B2": r+="test-03"
    return r

【讨论】:

df["C"] = df['C'].dt.date 解决了这个问题。不知道为什么:-(

以上是关于在 python 中,使用 lambda 将空列表添加到数据框列会引发 valueError的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 lambda 删除列表列表中数字下方的元素? Python [重复]

在python中使用lambda表达式在循环内生成函数

没有部分的python lambda函数列表

python--lambda表达式在sort函数中的使用

Python中使用列表生成式生成多个lambda函数逻辑错误

Python中使用列表生成式生成多个lambda函数逻辑错误