Python pandas将列表插入到单元格中

时间:2014-10-21 09:26:25

标签: python list pandas insert dataframe

我有一个列表'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

8 个答案:

答案 0 :(得分:71)

2017年更新

由于版本0.21.0后set_value已为deprecated,因此您现在应该使用at。它可以将列表插入到单元格中,而不会像ValueError那样提升loc。我认为这是因为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

答案 1 :(得分:35)

df3.set_value(1, 'B', abc)适用于任何数据框。请注意列' B'的数据类型。例如。列表无法插入到浮点列中,在这种情况下df['B'] = df['B'].astype(object)可以提供帮助。

答案 2 :(得分:5)

v0.23 +,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”第二行中的值设置为某些新列表,请使用DataFrane.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]

答案 3 :(得分:2)

如本文pandas: how to store a list in a dataframe?所述;数据框中的dtypes可能会影响结果,也可能会调用数据帧或不分配数据帧。

答案 4 :(得分:0)

快速解决

只需将列表括在新列表中,就像在下面数据框中的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]

答案 5 :(得分:0)

也得到

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

在我的情况下,使用.at而不是.loc并没有什么区别,但是强制使用dataframe列的数据类型可以达到目的:

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

然后我可以将列表,numpy数组和所有类型的东西设置为数据框中的单个单元格值。

答案 6 :(得分:0)

我有一个非常容易实现的解决方案。

制作一个临时类来包装列表对象,然后再从该类中调用值。

这是一个实际的例子:

  1. 假设您要将列表对象插入数据框。
df = pd.DataFrame([
    {'a': 1},
    {'a': 2},
    {'a': 3},
])

df.loc[:, 'b'] = [
    [1,2,4,2,], 
    [1,2,], 
    [4,5,6]
] # This works. Because the list has the same length as the rows of the dataframe

df.loc[:, 'c'] = [1,2,4,5,3] # This does not work. 

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

## To force pandas to have list as value in each cell, wrap the list with a temporary class.

class Fake(object):
    def __init__(self, li_obj):
        self.obj = li_obj

df.loc[:, 'c'] = Fake([1,2,5,3,5,7,]) # This works. 

df.c = df.c.apply(lambda x: x.obj) # Now extract the value from the class. This works. 

创建一个伪造的类来做到这一点看起来很麻烦,但是可以有一些实际的应用。例如,当返回值为list时,可以将其与apply一起使用。

熊猫通常会拒绝将列表插入到单元格中,但是如果使用此方法,则可以强制插入。

答案 7 :(得分:0)

我更喜欢 .at.loc。需要注意的是,目标列需要一个 dtype (object),它可以处理列表。

import numpy as np
import pandas as pd

df = pd.DataFrame({
    'A': [0, 1, 2, 3],
    'B': np.array([np.nan]*3 + [[3, 33]], dtype=object),
    })
print('df to start with:', df, '\ndtypes:', df.dtypes, sep='\n')

df.at[0, 'B'] = [0, 100]  # at assigns single elemnt
df.loc[1, 'B'] = [[ [1, 11] ]]  # loc expects 2d input

print('df modified:', df, '\ndtypes:', df.dtypes, sep='\n')

输出

df to start with:
   A        B
0  0      NaN
1  1      NaN
2  2      NaN
3  3  [3, 33]

dtypes:
A     int64
B    object
dtype: object
df modified:
   A          B
0  0   [0, 100]
1  1  [[1, 11]]
2  2        NaN
3  3    [3, 33]

dtypes:
A     int64
B    object
dtype: object