Python:合并列表或数据帧并覆盖缺少的值
假设我有以下列表:Python:合并列表或数据帧并覆盖缺少的值,python,pandas,merge,Python,Pandas,Merge,假设我有以下列表: list1 = ['MI', '', 'NY', '', 'AR', ''] list2 = ['', 'MS', '', 'OH', '', ''] 在列表1中任何缺少值或空字符串的地方,我都希望用列表2中相应的值覆盖空字符串。有没有一种有效的方法可以做到这一点,而不必遍历列表1中的每一项?以下是我当前的解决方案: list1 = ['MI', '', 'NY', '', 'AR', ''] list2 = ['', 'MS', '', 'OH', '', ''] co
list1 = ['MI', '', 'NY', '', 'AR', '']
list2 = ['', 'MS', '', 'OH', '', '']
在列表1中任何缺少值或空字符串的地方,我都希望用列表2中相应的值覆盖空字符串。有没有一种有效的方法可以做到这一点,而不必遍历列表1中的每一项?以下是我当前的解决方案:
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()
,但没有得到我想要的结果。类似的问题也解决了,但在R.中有一种更为“Pythonic”的方法(使用列表理解),但最终还是会得到一次迭代:
[x or y for x, y in zip(list1, list2)]
也许这会有帮助:
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', '']
必须在序列上迭代以查找缺少的值,使用前面的函数可以避免跟踪列表的索引
对不起,我的英语不好您可以使用pandas方法,但我想还有一个迭代:
>>> s1 = pd.Series(list1)
>>> s2 = pd.Series(list2)
>>> s1.where(s1 != '', s2)
0 MI
1 MS
2 NY
3 OH
4 AR
5
关于您最初的方法,您不必拥有自己的计数器,顺便说一句,您可以使用以下方法:
但更好的解决办法是使用和
如果您不需要立即列出,最好使用:
>>> 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', '']
或者,使用和来自:
不,您必须遍历。您可以使用花哨的列表comp之类的方法隐藏迭代,但是会有东西在幕后通过这些列表进行迭代。由于这会并行地在两个列表上进行迭代,那么它的效率可能会低于初始解决方案,该解决方案只完全迭代列表1,而只访问列表2的特定索引。想法?很好!这会完全迭代s1和s2吗?如果是这样的话,很可能是O(n2),而问题的答案似乎是O(n)。进一步思考?如果它对s1的每个元素迭代s2,那么它将是O(n2)。这两种解决方案都是O(n),您可以测试这两种方案,看看哪种更快。Pandas one可能会更快,因为它可以更快地访问该系列的元素(下面是numpy阵列)
>>> map(lambda x: x[1] if not x[0] else x[0], zip(list1, list2))
['MI', 'MS', 'NY', 'OH', 'AR', '']
>>> 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', '']
>>> 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', '']