【问题标题】:Python: merge lists or data frames and overwrite missing valuesPython:合并列表或数据框并覆盖缺失值
【发布时间】:2014-12-03 04:24:02
【问题描述】:

假设我有以下列表:

list1 = ['MI', '', 'NY', '', 'AR', '']
list2 = ['', 'MS', '', 'OH', '', '']

list1 中有缺失值或空字符串的地方,我想用 list2 中的对应值覆盖空字符串。有没有一种有效的方法可以做到这一点,而不必遍历 list1 中的每个项目?以下是我目前的解决方案:

list1 = ['MI', '', 'NY', '', 'AR', '']
list2 = ['', 'MS', '', 'OH', '', '']

counter = 0

for each in list1:
    counter = counter + 1
    if len(each) == 0:
        list1[counter-1] = list2[counter-1]
print(list1)
>>> ['MI', 'MS', 'NY', 'OH', 'AR', '']

我尝试将我的列表转换为 pandas 数据框并使用了pandas.DataFrame.update(),但没有得到我想要的结果。 here 解决了类似的问题,但在 R 中。

【问题讨论】:

  • 不,您将不得不迭代。您可以通过使用精美的列表组合等来隐藏迭代,但有些东西会在幕后迭代这些列表。

标签: python pandas merge


【解决方案1】:

还有一种更“Pythonic”的方法(使用列表推导式),但最终你仍然会得到一个迭代:

[x or y for x, y in zip(list1, list2)]

【讨论】:

  • 由于这会并行迭代两个列表,因此它的效率可能低于仅完全迭代 list1 但仅访问 list2 的特定索引的初始解决方案。想法?
【解决方案2】:

你可以使用 pandas pandas.Series.where() 方法,但我想还有一个迭代:

>>> s1 = pd.Series(list1)
>>> s2 = pd.Series(list2)
>>> s1.where(s1 != '', s2)
0    MI
1    MS
2    NY
3    OH
4    AR
5      

关于你原来的方法,你不必有自己的计数器,顺便说一句,你可以使用enumerate()方法:

>>> def isnull1(list1, list2):
...     res = []
...     for i, x in enumerate(list1):
...         if not x:
...             res.append(list2[i])
...         else:
...             res.append(x)
...     return res
... 
>>> isnull1(list1, list2)
['MI', 'MS', 'NY', 'OH', 'AR', '']

但更好的解决方案是使用zip()map()

>>> map(lambda x: x[1] if not x[0] else x[0], zip(list1, list2))
['MI', 'MS', 'NY', 'OH', 'AR', '']

如果您不需要立即列出列表,最好使用generators

>>> def isnull2(list1, list2):
...     for i, x in enumerate(list1):
...         if not x:
...             yield list2[i]
...         else:
...             yield x
... 
>>> list(isnull2(list1, list2))
['MI', 'MS', 'NY', 'OH', 'AR', '']

或者,使用来自itertoolsimap()izip()

>>> from itertools import izip, imap
>>> list(imap(lambda x: x[1] if not x[0] else x[0], izip(list1, list2)))
['MI', 'MS', 'NY', 'OH', 'AR', '']

【讨论】:

  • 不错!这会完全迭代 s1 和 s2 吗?如果是这样,它可能是 O(n2),而问题中的解决方案似乎是 O(n)。进一步的想法?
  • 如果它为 s1 的每个元素迭代 s2,那么它将是 O(n2)。两种解决方案都是 O(n),您可以测试两者以查看哪个更快。 Pandas 可能会更快,因为可以更快地访问 Series 的元素(下面是 numpy 数组)
【解决方案3】:

也许这会有所帮助:

def list_default(l1, l2):
    i1 = iter(l1)
    i2 = iter(l2)
    for i in i1:
        next_default = i2.next()
        if not i:
            yield next_default
        else:
            yield i

list1 = ['MI', '', 'NY', '', 'AR', '']
list2 = ['', 'MS', '', 'OH', '', '']

print(list(list_default(list1, list2)))
>>> ['MI', 'MS', 'NY', 'OH', 'AR', '']

您必须遍历序列以查找缺失值,避免使用前面的函数来跟踪列表的索引。

对不起我的英语

【讨论】:

    猜你喜欢
    • 2019-03-24
    • 2018-05-27
    • 2020-10-28
    • 2013-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多