【问题标题】:Apply a function pairwise on a pandas series在熊猫系列上成对应用函数
【发布时间】:2017-09-25 18:23:32
【问题描述】:

我有一个 pandas 系列,其元素构成了 freezesets:

data = {0: frozenset({'apple', 'banana'}),
     1: frozenset({'apple', 'orange'}),
     2: frozenset({'banana'}),
     3: frozenset({'kumquat', 'orange'}),
     4: frozenset({'orange'}),
     5: frozenset({'orange', 'pear'}),
     6: frozenset({'orange', 'pear'}),
     7: frozenset({'apple', 'banana', 'pear'}),
     8: frozenset({'banana', 'persimmon'}),
     9: frozenset({'apple'}),
     10: frozenset({'banana'}),
     11: frozenset({'apple'})}

tokens = pd.Series(data); tokens

0           (apple, banana)
1           (orange, apple)
2                  (banana)
3         (orange, kumquat)
4                  (orange)
5            (orange, pear)
6            (orange, pear)
7     (apple, banana, pear)
8       (persimmon, banana)
9                   (apple)
10                 (banana)
11                  (apple)
Name: Tokens, dtype: object

我想成对应用一个函数。例如,tokens.diff 给了我连续行之间的差异:

0                   NaN
1              (orange)
2              (banana)
3     (orange, kumquat)
4                    ()
5                (pear)
6                    ()
7       (apple, banana)
8           (persimmon)
9               (apple)
10             (banana)
11              (apple)
Name: Tokens, dtype: object

我想要同样的东西,但不是设置差异,我想要在连续行上设置联合。所以,我最理想的情况是:

0                                 NaN
1             (orange, apple, banana)
2             (banana, orange, apply)
3           (orange, kumquat, banana)
4                   (orange, kumquat)
                                  ...

如何使用 Pandas 实现这一目标?我知道我可以使用zip 和列表组合来做到这一点,但希望有更好的方法。

【问题讨论】:

  • 在最后一段代码中,您不是想把tokens.diff() 留在里面,对吗?
  • @IanS 不,感谢收看。
  • 嗯...这是受到不久前提出的一个问题的启发 :)
  • @JonClements 你明白了。我几乎解决了它,这是最后一个障碍。
  • @Zero 想到了这个......希望避免因为我需要在 groupby 操作中使用结果,所以有用的代码意味着更多的问题。您可以将其写在答案中,我会投赞成票,但除非真的没有其他办法,否则我不会接受。

标签: python pandas dataframe set frozenset


【解决方案1】:

几种方法

选项 1] 列表理解

In [3631]: pd.Series([x[0].union(x[1])
                      for x in zip(tokens, tokens.shift(-1).fillna(''))],
                     index=tokens.index)
Out[3631]:
0              (orange, banana, apple)
1              (orange, apple, banana)
2            (orange, kumquat, banana)
3                    (orange, kumquat)
4                       (orange, pear)
5                       (orange, pear)
6        (orange, pear, banana, apple)
7     (persimmon, pear, banana, apple)
8           (apple, persimmon, banana)
9                      (apple, banana)
10                     (banana, apple)
11                             (apple)
dtype: object

选项 2] map

In [3632]: pd.Series(map(lambda x: x[0].union(x[1]), 
                         zip(tokens, tokens.shift(-1).fillna(''))),
                     index=tokens.index)
Out[3632]:
0              (orange, banana, apple)
1              (orange, apple, banana)
2            (orange, kumquat, banana)
3                    (orange, kumquat)
4                       (orange, pear)
5                       (orange, pear)
6        (orange, pear, banana, apple)
7     (persimmon, pear, banana, apple)
8           (apple, persimmon, banana)
9                      (apple, banana)
10                     (banana, apple)
11                             (apple)
dtype: object

选项 3] 使用 concatapply

In [3633]: pd.concat([tokens, tokens.shift(-1).fillna('')],
                     axis=1).apply(lambda x: x[0].union(x[1]), axis=1)
Out[3633]:
0              (orange, banana, apple)
1              (orange, apple, banana)
2            (orange, kumquat, banana)
3                    (orange, kumquat)
4                       (orange, pear)
5                       (orange, pear)
6        (orange, pear, banana, apple)
7     (persimmon, pear, banana, apple)
8           (apple, persimmon, banana)
9                      (apple, banana)
10                     (banana, apple)
11                             (apple)
dtype: object

时间

In [3647]: tokens.shape
Out[3647]: (60000L,)

In [3648]: %timeit pd.Series([x[0].union(x[1]) for x in zip(tokens, tokens.shift(-1).fillna(''))], index=tokens.index)
10 loops, best of 3: 35 ms per loop

In [3649]: %timeit pd.Series(map(lambda x: x[0].union(x[1]), zip(tokens, tokens.shift(-1).fillna(''))), index=tokens.index)
10 loops, best of 3: 40.9 ms per loop

In [3650]: %timeit pd.concat([tokens, tokens.shift(-1).fillna('')], axis=1).apply(lambda x: x[0].union(x[1]), axis=1)
1 loop, best of 3: 2.2 s per loop

无关,为了diff上的号码

In [3653]: %timeit tokens.diff()
10 loops, best of 3: 10.8 ms per loop

【讨论】:

  • 我以为我需要 shift(-1),但实际上最终需要 shift()。 stackoverflow.com/a/46402641/4909087
  • 一个很棒的解决方案先生,我也想出了另一个选项,但无法击败列表理解,即pd.Series(tokens.apply(list) + tokens.shift(-1).fillna('').apply(list),index=tokens.index).apply(set)
猜你喜欢
  • 1970-01-01
  • 2017-02-07
  • 1970-01-01
  • 2022-11-13
  • 1970-01-01
  • 2020-06-03
  • 2021-07-01
  • 1970-01-01
  • 2018-02-09
相关资源
最近更新 更多