对序列的集合操作

1 投票
1 回答
1467 浏览
提问于 2025-04-17 17:02

我在想有没有人能帮我解决一个问题;我基本上有一个用pandas的字符串操作创建的列表系列(用空格分隔) - str.split(' ')。我需要创建另一个列表系列,这个系列是每个列表与另一个列表的交集。

我觉得这里缺少的部分是apply(),但我用法可能不对,所以收到了错误提示。使用apply()中的集合操作在pandas手册里并没有详细说明,但我觉得应该可以做到吧?

简单来说,我有一组事件(evector),我想建立一个向量,表示哪些事件与给定事件(e2)共享用户。

这是我到目前为止的尝试:

最初的尝试:

evector = attendframe.yes.str.split(' ') #creates the series of lists

e2 = [attendframe.yes[attendframe.event==686467261]] #just for testing - returns [0
  #  1975964455 252302513 4226086795 3805886383 142...
  #Name: yes]

sharedvector = evector.apply(lambda x: [n for n in [x] if n in e2]) # the important bit

print sharedvector

错误: 数组长度不同:1 vs 7

我把问题缩小到以下这一行: evector = attendframe.yes.str.split(' ').apply(lambda x: set([x]))

然后我又做了几次尝试,希望能搞定。

尝试 1

evector = attendframe.yes.str.split(' ').apply(lambda x: set([x]))
#Unhashable type "list"

尝试 2

evector = attendframe.yes.str.split(' ').apply(lambda x: set(x))
#TypeError: 'float' object is not iterable

尝试 3(感谢Andy Hayden)

evector = attendframe.yes.str.split(' ').apply(lambda x: x
                                                if isinstance(x, float)
                                                else set(x))

e2 = set([2394228942, 2686116898, 1056558062, 379294223])
sharedvector = evector.apply(lambda x: x if isinstance(x, float) else x.intersection(e2))
sharedvector.dropna())
#works, but returns empty arrays.

这里是导致问题的数据示例:

print attendframe.yes.str.split(' ')

0     [1975964455, 252302513, 4226086795, 3805886383...
1     [2394228942, 2686116898, 1056558062, 379294223...
2                                                   NaN
3                                                   NaN

如果这对最终解决方案有任何帮助,我最终想创建一个数据框,边缘包含事件,单元格包含任何两个给定事件之间共享的用户列表。生成列向量是第一步,然后我希望在这个基础上运行类似的apply()步骤,创建完整的矩阵。

1 个回答

1

既然你在问集合操作,为什么不使用set对象呢:

evector = attendframe.yes.str.split(' ').apply(set)
e2 = set(attendframe[attendframe.event==686467261]]['yes'])

然后可以使用集合的交集操作:

sharedvector = evector.apply(lambda x: x & e2)

如果你的数据中有NaN(表示不是一个数字),你可以在每次调用集合的时候,先检查一下它是不是一个浮点数:

evector = df.yes.str.split(' ').apply(lambda x: x
                                                if isinstance(x, float)
                                                else set(x))
e2 = set(attendframe[attendframe.event==686467261]]['yes'])
sharedvector = evector.apply(lambda x: x if isinstance(x, float) else x & e2)

撰写回答