我有一个列表'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'] = abc
或df3.loc[1,'B'] = abc
。
另一个数据框:
df4 =
A B
0 'bla' NaN
1 'bla bla' NaN
这些插页完美运行:df.loc[1,'B'] = abc
或df4.loc[1,'B'] = abc
。
答案 0 :(得分:71)
由于版本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)
我有一个非常容易实现的解决方案。
制作一个临时类来包装列表对象,然后再从该类中调用值。
这是一个实际的例子:
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