我尝试在pandas中有条件地附加一个列表列表:
import pandas as pd
df = pd.DataFrame(data={'A': [1, 2, 3]})
df['B'] = [[[1],[1],[1]]] * df.shape[0]
df
A B
0 1 [[1], [1], [1]]
1 2 [[1], [1], [1]]
2 3 [[1], [1], [1]]
# attempting to append 1st list of lists in B column with 2
df['B'] = df['B'].mask(df.A == 2, df['B'].apply(lambda x: x[0].append(2)))
df
A B
0 1 [[1, 2, 2, 2], [1], [1]]
1 2 None
2 3 [[1, 2, 2, 2], [1], [1]]
#expected result I'm hoping for is:
df['B'] = [[[1],[1],[1]],[[1,2],[1],[1]],[[1],[1],[1]]]
df
A B
0 1 [[1], [1], [1]]
1 2 [[1, 2], [1], [1]]
2 3 [[1], [1], [1]]
4条答案
按热度按时间yduiuuwa1#
尝试使用lambda函数有条件地修改列表列表,如下所示:
在这里,我们创建一个新的列表列表,其中包括修改后的列表,然后返回该列表。
apply
方法在axis=1的整个DataFrame上调用,以按行应用lambda函数。68bkxrlz2#
list.append
在适当的位置工作,所以它实际上返回None
而不是一个列表。这就是为什么你的新df在第二行有None
。下面是一个将2添加到列表中的方法。我们取第二行中的第一个列表并添加
[2]
,然后解包其余的列表以形成预期的输出:输出:
kyvafyod3#
iswrvxsc4#
问题在于如何生成数据框:
[[[1],[1],[1]]] * df.shape[0]
在Python中是一个棘手的东西。因为df
中不同行的所有[[1],[1],[1]]
都指向同一个对象,即列表[[1], [1], [1]]
。试试这个:
.at[ ]
允许您同时使用索引号和列名进行访问。[0]
选择访问后返回的列表的第一个元素。所以这里不需要lambda
。我们认为只有第二行的'B'列'列表中的第一个元素
[[1], [1], [1]]
被更改为[[1, 2], [1], [1]]
。但如果你看整个数据框:它返回:
因为
B
中的元素都指向同一个对象,所以它们会同时发生变异。这就是为什么在生成这样的构造时应该避免
[ ] * <number>
。相反,使用e。g.列表理解:
避免在lambda中使用
append
怎么样:
可以使用
np.where()
来获取行索引: