【问题标题】:python pandas DataFrame.apply: return a series instead of a dataframepython pandas DataFrame.apply:返回一个系列而不是一个数据框
【发布时间】:2018-11-22 15:34:51
【问题描述】:

我正在尝试按行(轴 = 1)将函数应用于 DataFrame,当应用的函数返回一个系列时,'apply' 的最终返回值将是一个数据帧,这不是我的想。 我在这里发现了一个类似的问题,Returning multiple values from pandas apply on a DataFrame,但是这个案例是关于将函数应用于 groupby。 并且在非分组的情况下,即使返回的一系列应用函数的长度不同,也会返回一个数据帧。

In [10]: import pandas as pd

In [11]: import numpy as np

In [12]: df = pd.DataFrame({'start': [1, 2, 3], 'end': [7, 9, 9]})

In [13]: df
Out[13]:
   end  start
0    7      1
1    9      2
2    9      3

In [14]: def fun(df):
    ...:     return pd.Series(np.arange(df['start'], df['end'], 1))
    ...:

In [15]: df.apply(fun, axis=1)
Out[15]:
     0    1    2    3    4    5    6
0  1.0  2.0  3.0  4.0  5.0  6.0  NaN
1  2.0  3.0  4.0  5.0  6.0  7.0  8.0
2  3.0  4.0  5.0  6.0  7.0  8.0  NaN

但是,我想要的是这样的(分层系列):

Out[23]:
0  0    1.0
   1    2.0
   2    3.0
   3    4.0
   4    5.0
   5    6.0
1  0    2.0
   1    3.0
   2    4.0
   3    5.0
   4    6.0
   5    7.0
   6    8.0
2  0    3.0
   1    4.0
   2    5.0
   3    6.0
   4    7.0
   5    8.0
dtype: float64

【问题讨论】:

  • 你能添加一些数据样本吗?
  • 欢迎来到 StackOverflow。请花时间阅读how to provide a great pandas example 上的这篇文章以及如何提供minimal, complete, and verifiable example 并相应地修改您的问题。 how to ask a good question 上的这些提示也可能有用。
  • 好的,请稍等,谢谢。
  • 在 [10] 中:将 pandas 导入为 pd 在 [11] 中:将 numpy 导入为 np 在 [12] 中:df = pd.DataFrame({'start': [1, 2, 3], 'end': [7, 9, 9]}) In [13]: df Out[13]: end start 0 7 1 1 9 2 2 9 3 In [14]: def fun(df): ...:返回 pd.Series(np.arange(df['start'], df['end'], 1)) ...: In [15]: df.apply(fun, axis=1) Out[15]: 0 1 2 3 4 5 6 0 1.0 2.0 3.0 4.0 5.0 6.0 NaN 1 2.0 3.0 4.0 5.0 6.0 7.0 8.0 2 3.0 4.0 5.0 6.0 7.0 8.0 NaN
  • 请编辑问题:)

标签: python pandas dataframe apply


【解决方案1】:

这里apply 将值转换为DataFrame 进行设计,因此可能的解决方案是使用stack

s = df.apply(fun, axis=1).stack()
print (s)
0  0    1.0
   1    2.0
   2    3.0
   3    4.0
   4    5.0
   5    6.0
1  0    2.0
   1    3.0
   2    4.0
   3    5.0
   4    6.0
   5    7.0
   6    8.0
2  0    3.0
   1    4.0
   2    5.0
   3    6.0
   4    7.0
   5    8.0
dtype: float64

或者list comprehensionconcat

L = [pd.Series(np.arange(a, b)) for a, b in zip(df['start'], df['end'])]
s = pd.concat(L, keys=df.index)
print (s)
0  0    1
   1    2
   2    3
   3    4
   4    5
   5    6
1  0    2
   1    3
   2    4
   3    5
   4    6
   5    7
   6    8
2  0    3
   1    4
   2    5
   3    6
   4    7
   5    8
dtype: int32

【讨论】:

  • 谢谢jezrael,问题是我有一个量级的大数据,这可能会耗尽我的整个RAM,如果'apply'函数返回一个DataFram,它可能有太多列(列数是等于应用函数返回的最长序列)。同样,由于行太多,我不能使用“for”。
  • @WoodsChen - 无法使用第二种解决方案?
  • 不,我也试过了,这可能会更快地耗尽内存,可能是由于“for”循环和 zip 操作。
  • @WoodsChen - 嗯,如果使用 return np.arange(df['start'], df['end'], 1) 可以吗?
  • 嗯,我试过了,又失败了。使用 Python 3.6.2/ IPython 6.2.1/ Windows 时:由于列不匹配而引发错误。使用 Python 3.6.5/ IPython 6.4.0/ Ubuntu 时:它返回了一个序列,其中所有值都是一个列表(np.arange 的返回值),但这仍然不是我想要的。
猜你喜欢
  • 2022-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-30
相关资源
最近更新 更多