Python pandas 将列表插入单元格

176 投票
9 回答
255820 浏览
提问于 2025-04-28 18:22

我有一个列表 'abc' 和一个数据框 'df':

abc = ['foo', 'bar']
df =
    A  B
0  12  NaN
1  23  NaN

我想把这个列表放到单元格 1B 里,所以我想要这样的结果:

    A  B
0  12  NaN
1  23  ['foo', 'bar']

我该怎么做呢?

1) 如果我这样做:

df.ix[1,'B'] = abc

我会收到以下错误信息:

ValueError: Must have equal len keys and value when setting with an iterable

因为它试图把这个有两个元素的列表放到一行/一列里,而不是放到一个单元格里。

2) 如果我这样做:

df.ix[1,'B'] = [abc]

那么它只会插入一个元素的列表,就是 'abc' 列表( [['foo', 'bar']] )。

3) 如果我这样做:

df.ix[1,'B'] = ', '.join(abc)

那么它插入的是一个字符串:( foo, bar )而不是一个列表。

4) 如果我这样做:

df.ix[1,'B'] = [', '.join(abc)]

那么它插入了一个列表,但只有一个元素( ['foo, bar'] ),而不是我想要的两个元素( ['foo', 'bar'] )。

谢谢大家的帮助!


编辑

这是我新的数据框和旧的列表:

abc = ['foo', 'bar']
df2 =
    A    B         C
0  12  NaN      'bla'
1  23  NaN  'bla bla'

另一个数据框:

df3 =
    A    B         C                    D
0  12  NaN      'bla'  ['item1', 'item2']
1  23  NaN  'bla bla'        [11, 12, 13]

我想把 'abc' 列表插入到 df2.loc[1,'B'] 和/或 df3.loc[1,'B']

如果数据框的列只有整数值和/或 NaN 值和/或列表值,那么把列表插入到单元格里是完全没问题的。如果数据框的列只有字符串值和/或 NaN 值和/或列表值,那么插入列表也没问题。但是如果数据框的列同时有整数和字符串值以及其他列,那么当我使用 df2.loc[1,'B'] = abcdf3.loc[1,'B'] = abc 时,就会出现错误信息。

另一个数据框:

df4 =
          A     B
0      'bla'  NaN
1  'bla bla'  NaN

这些插入操作完全没问题: df.loc[1,'B'] = abcdf4.loc[1,'B'] = abc

暂无标签

9 个回答

7

我也遇到了这个问题:

ValueError: Must have equal len keys and value when setting with an iterable

在我的情况下,使用 .at 代替 .loc 并没有什么区别,但强制设置数据框列的数据类型解决了这个问题:

df['B'] = df['B'].astype(object)

这样我就可以把列表、numpy 数组以及各种东西作为单个单元格的值放进我的数据框里了。

8

快速解决方法

只需把这个列表放在一个新的列表里,就像下面数据表中的col2那样。这样做的原因是,Python会把外面的这个列表(包含多个列表)当作一列来处理,就好像里面是普通的单个项一样,而实际上我们这里的内容是列表,而不是普通的单个项。

mydict={'col1':[1,2,3],'col2':[[1, 4], [2, 5], [3, 6]]}
data=pd.DataFrame(mydict)
data


   col1     col2
0   1       [1, 4]
1   2       [2, 5]
2   3       [3, 6]
63

Pandas >= 0.21

set_value这个功能已经被淘汰了。现在你可以使用 DataFrame.at 来通过标签设置值,使用 DataFrame.iat 来通过整数位置设置值。

使用 at/iat 设置单元格值

# Setup
>>> df = pd.DataFrame({'A': [12, 23], 'B': [['a', 'b'], ['c', 'd']]})
>>> df

    A       B
0  12  [a, b]
1  23  [c, d]

>>> df.dtypes

A     int64
B    object
dtype: object

如果你想把“B”列的第二行的值设置为一个新的列表,可以使用 DataFrame.at

>>> df.at[1, 'B'] = ['m', 'n']
>>> df

    A       B
0  12  [a, b]
1  23  [m, n]

你也可以通过整数位置来设置值,使用 DataFrame.iat

>>> df.iat[1, df.columns.get_loc('B')] = ['m', 'n']
>>> df

    A       B
0  12  [a, b]
1  23  [m, n]

如果我遇到 ValueError: setting an array element with a sequence 怎么办?

我会尝试用以下代码重现这个问题:

>>> df
    A   B
0  12 NaN
1  23 NaN

>>> df.dtypes
A      int64
B    float64
dtype: object
>>> df.at[1, 'B'] = ['m', 'n']
# ValueError: setting an array element with a sequence.

这个错误是因为你的对象是 float64 类型,而列表是 object 类型,所以类型不匹配。在这种情况下,你需要先把这一列转换成对象类型。

>>> df['B'] = df['B'].astype(object)
>>> df.dtypes

A     int64
B    object
dtype: object

这样就可以正常工作了:

>>> df.at[1, 'B'] = ['m', 'n']
>>> df
    
    A       B
0  12     NaN
1  23  [m, n]

可能,但有点奇怪

DataFrame.loc 来实现类似的功能,如果你传递的是嵌套列表。

>>> df.loc[1, 'B'] = [['m'], ['n'], ['o'], ['p']]
>>> df

    A             B
0  12        [a, b]
1  23  [m, n, o, p]

你可以在 这里 阅读更多关于为什么这样做有效的信息。

205

因为从0.21.0版本开始,set_value这个功能已经被淘汰了,所以现在你应该使用at。这个功能可以在一个单元格里插入一个列表,而不会像loc那样引发ValueError错误。我觉得这是因为at总是指向一个单一的值,而loc可以指向多个值、行和列。

df = pd.DataFrame(data={'A': [1, 2, 3], 'B': ['x', 'y', 'z']})

df.at[1, 'B'] = ['m', 'n']

df =
    A   B
0   1   x
1   2   [m, n]
2   3   z

你还需要确保你要插入的那一列的类型是dtype=object。比如说:

>>> df = pd.DataFrame(data={'A': [1, 2, 3], 'B': [1,2,3]})
>>> df.dtypes
A    int64
B    int64
dtype: object

>>> df.at[1, 'B'] = [1, 2, 3]
ValueError: setting an array element with a sequence

>>> df['B'] = df['B'].astype('object')
>>> df.at[1, 'B'] = [1, 2, 3]
>>> df
   A          B
0  1          1
1  2  [1, 2, 3]
2  3          3
42

df3.set_value(1, 'B', abc) 这个方法可以在任何数据表中使用。要注意列 'B' 的数据类型。例如,如果你想往一个浮点数类型的列里插入一个列表,那是行不通的。在这种情况下,可以用 df['B'] = df['B'].astype(object) 这个方法来解决问题,把 'B' 列的类型改成对象类型。

撰写回答