【问题标题】:Optimising concatenation in Python on Pandas dataframe在 Pandas 数据帧上优化 Python 中的连接
【发布时间】:2017-03-10 10:55:24
【问题描述】:

我有一个数据框,出于 MVP 的目的,它看起来像:

Val_x, Val_y
NaN, 2
1, Nan

我正在尝试生成一个新列val,它是这两者的串联。

目前我正在通过:

df['Val']=[df.iloc[j]['Val_x'] if pd.isnull(df.iloc[j]['Val_y']) else df.iloc[j]['Val_y'] for j in range(len(df))]

但这不是很高效,也不是很pythonic/pandas-native。

即我想到达:

Val_x, Val_y, val
Nan,    2,    2
1,    NaN,    1

然后我可以在哪里做drop(val_x),drop(val_y)

如果有人有指点,我将不胜感激?

谢谢

编辑:

我正在尝试生成一个新列,它实际上是另外两列的“Non-NAN”值。这样做的原因是,出于技术原因,我不得不将我的数据框分成两个对象以进行不同的处理,现在希望重新加入它。所以我的原始数据框是index, val,我现在有一个新的数据框index, val_x, val_y,其中一些val_xNaN,而一些val_yNaN,但绝不是两者都有@ 987654332@,现在希望再次将其简化为一列

【问题讨论】:

  • 你能解释一下你想做什么吗?
  • 当然。我会更新 OP。

标签: python pandas


【解决方案1】:

UPDATE3:这里是a brilliant generic vectorized solution from @AndyJones, which finds first non-null value per row

df['new'] = df.T.bfill().iloc[0]

UPDATE2: 400.000 行 DF 的时间

In [269]: df = pd.concat([df] * 10**5, ignore_index=True)

In [270]: df.shape
Out[270]: (400000, 2)

In [271]: %timeit df['Val_x'].fillna(df['Val_y'])
10 loops, best of 3: 127 ms per loop

In [272]: %timeit df['Val_y'].where(df['Val_y'].notnull(), df['Val_x'])
10 loops, best of 3: 98.9 ms per loop

In [273]: %timeit np.where(df['Val_x'].notnull(), df['Val_x'], df['Val_y'])
10 loops, best of 3: 31 ms per loop

更新:

df['Val'] = df['Val_x'].fillna(df['Val_y'])

旧答案:

这是一个通用的(应该​​适用于任意数量的列),但速度较慢 (.apply(..., axis=1)) 的解决方案:

In [256]: df
Out[256]:
   Val_x Val_y
0    NaN     2
1    1.0   Nan
2    2.0     3
3    NaN   NaN

In [257]: df['Val'] = df.apply(lambda x: x[x.first_valid_index()] if x.first_valid_index()
                                         else np.nan,
                               axis=1)

In [258]: df
Out[258]:
   Val_x Val_y  Val
0    NaN     2    2
1    1.0   Nan    1
2    2.0     3    2
3    NaN   NaN  NaN

【讨论】:

  • 谢谢,一位同事也为我解决了这个问题,并将发布他的答案:)
【解决方案2】:

一位同事为我解决了这个问题:

df['Val'] = df['Val_y'].where(df['Val_y'].notnull(), df['Val_x'])

对于基准测试参考,在我的数据框架上,原始代码运行大约需要 22 秒,我在此处的答案中提供的版本运行时间不到 1 秒。我没有尝试对 MaxU 的建议进行基准测试。

【讨论】:

  • 这会比我的快得多。我试图找到一个适用于 3 列以上的通用解决方案...我为您的特定情况添加了另一个解决方案...
  • 感谢您的信息:)
【解决方案3】:

您可以为 0 和总和列填充 NaN:

data = [[1,numpy.nan],[numpy.nan,4]]
df = DataFrame(data, columns=['col1','col2'])
df:
   col1  col2
0   1.0   NaN
1   NaN   4.0
df = df.fillna(0)
df['col3'] = df['col1']+df['col2']
df:
   col1  col2  col3
0   1.0   0.0   1.0
1   0.0   4.0   4.0

【讨论】:

  • 哦,这很聪明,我喜欢它。一般不适用于非数字数据,但总体上非常优雅。
  • 这仅适用于每行只有一个“非空”值的情况。在这种情况下,我们可以使用:df['col3'] = df.sum(axis=1)
猜你喜欢
  • 1970-01-01
  • 2020-04-07
  • 2019-11-17
  • 1970-01-01
  • 2022-06-21
  • 2019-02-02
  • 2019-02-01
  • 2016-11-18
  • 2020-09-02
相关资源
最近更新 更多