用数据框的行值替换子列表中的第二项

Posted

技术标签:

【中文标题】用数据框的行值替换子列表中的第二项【英文标题】:Replace second item in sublist with row value of dataframe 【发布时间】:2017-10-11 22:15:16 【问题描述】:

我有一个嵌套列表,并且想用数据框的行值替换每个子列表的第二项。这是我的数据框和列表:

import pandas as pd
mydata = ['id' : '12',
          'id' : '34',
          'id' : '56',
          'id' : '78',]
df = pd.DataFrame(mydata)

L1 = [ ['elephant',0], ['zebra',1], ['lion',2], ['giraffe',3]  ]

期望的结果是:[ ['elephant',12], ['zebra',34], ['lion',56], ['giraffe',78] ]

这是我的代码:

for i in L1:
    for j, row in df.iterrows():
        i[1] = df["id"][j] 

哪个输出:[['elephant', '78'], ['zebra', '78'], ['lion', '78'], ['giraffe','78']]

【问题讨论】:

【参考方案1】:

EdChum 的回答当然是正确的,但对发生的事情几乎没有解释。我将解释您现有代码的问题,以及从那里开始的适当步骤。 (我的答案最终与 Ed 的相似但不同。我没有测试过哪个更有效,但可能我的答案更容易理解。)

为什么你会得到一个每个值都设置为 78 的结果?您的代码可以:

for i in L1:
    for j, row in df.iterrows():
        i[1] = df["id"][j] 

这意味着,对于L1 中的每个i,遍历df 中的每一行,并将i[1] 设置为该行的"id"。这意味着在这种情况下,您为每个 i 设置了 4 次 i[1],并且在循环结束时,它始终是最后一个值,因此是 '78'。您需要根据i[1] 的当前值选择性地设置i[1]

您可以按如下方式修改循环:

for i in L1:
    i[1] = df["id"][i[1]]

这会修改每个列表i,将其第二个值设置为df["id"] 的值以及原始i[1] 编号。这将产生您想要的结果。

不过,这不是很pythonic。一般来说,我们尽量避免python中的基本循环。最简洁的使用方法是使用列表推导,不像 Ed 那样复杂:

L1 = [[i[0], df["id"][i[1]]] for i in L1]

这和上面的循环一样,只是使用列表理解语法(所以它会快得多)。将zip 用于此功能非常好,但没有必要。

(注意,我的解决方案根本不使用 pandas。)

【讨论】:

不错的答案,在某些情况下,列表理解会更快,特别是对于小型数据集,如果数据集更大并且已经在 df 中,那么调用 .values.tolist() 应该会更快我预计 +1【参考方案2】:

使用列表推导生成第一个元素的列表,然后zip id 为 col:

In[32]:
list(zip([x[0] for x in L1], df['id'].tolist()))

Out[32]: [('elephant', '12'), ('zebra', '34'), ('lion', '56'), ('giraffe', '78')]

如果你坚持要一个列表,你可以把上面的变成一个列表:

In[35]:
L2 = list(zip([x[0] for x in L1], df['id'].tolist()))
L2

Out[35]: [('elephant', '12'), ('zebra', '34'), ('lion', '56'), ('giraffe', '78')]

In[36]:
[list(x) for x in L2]

Out[36]: [['elephant', '12'], ['zebra', '34'], ['lion', '56'], ['giraffe', '78']]

纯粹的 pandas 方法是从您的列表中构造一个 df:

In[41]:
df2 = pd.DataFrame(L1)
df2

Out[41]: 
          0  1
0  elephant  0
1     zebra  1
2      lion  2
3   giraffe  3

然后concatenate 他们:

In[43]:
merged = pd.concat([df,df2], axis=1)
merged

Out[43]: 
   id         0  1
0  12  elephant  0
1  34     zebra  1
2  56      lion  2
3  78   giraffe  3

然后只需子选择感兴趣的列并调用 .values 以返回一个 np 数组,然后是 tolist

In[46]:
merged[[0,'id']].values.tolist()

Out[46]: [['elephant', '12'], ['zebra', '34'], ['lion', '56'], ['giraffe', '78']]

【讨论】:

以上是关于用数据框的行值替换子列表中的第二项的主要内容,如果未能解决你的问题,请参考以下文章

将数据框中的行替换为 0,其前面的行值不同于 0

如何在由前一个元素的连续值和第二项中的零组成的列表中添加连续元素?

markdown列表

如何在TinyMCE的列表项中添加段落?

Markdown快速学习效果展示页

根据行号删除数据框的行