python - pandas groupby 索引:nan 冲突或只取值
问题描述
我正在处理一些数据,pandas
这些数据可能会有一些我需要处理的不一致之处。数据是值的时间序列:
A B C
YYYY MM DD hh mm
2017 8 20 23 0 1 2.0 NaN
10 2 4.0 NaN
20 3 6.0 NaN
30 4 8.0 NaN
... ... ... ...
2019 6 4 10 10 100 100 NaN
20 200 102 NaN
30 300 104 NaN
40 400 106 NaN
50 500 108 0
数据可能存在的不一致是同一["YYYY", "MM", "DD", "hh", "mm"]
索引的多个条目。在大多数情况下,当时的值是相同的,因此我可以使用df.drop_duplicates(keep="first")
删除具有相同索引和列值的所有行。
但是,存在索引冲突,其中值不相同或非 nan 值仅存在于其中一行中。我追求的行为是:
对于重复索引,基于每列:
- 如果只有一个非 nan 值:使用它。
- 如果所有 nan 值:使用 nan。
- 如果所有相同的(非nan)值:使用它。
- 如果不相等(non-nan)值:使用 nan。
例如(是一个简化的 DataFrame):
A B C
0 1 2.0 NaN
1 2 NaN NaN
1 100 500.0 NaN
2 3 6.0 NaN
2 200 6.0 NaN
3 300 8.0 NaN
3 300 NaN 5.0
3 300 NaN NaN
4 400 106.0 NaN
应该导致:
A B C
0 1.0 2.0 NaN
1 NaN 500.0 NaN
2 NaN 6.0 NaN
3 300.0 8.0 5.0
4 400.0 106.0 NaN
我试图用几种方法解决这个问题,但它们在数据集大小上都非常慢。
当前缓慢的解决方案(您可能需要滚动代码片段窗口):
import numpy as np
import pandas as pd
df = pd.DataFrame(
[
dict(A=1, B=2.0, C=None),
dict(A=2, B=None, C=None),
dict(A=100, B=500, C=None),
dict(A=3, B=6.0, C=None),
dict(A=200, B=6.0, C=None),
dict(A=300, B=8.0, C=None),
dict(A=300, B=None, C=5.0),
dict(A=300, B=None, C=None),
dict(A=400, B=106, C=None),
],
index=[0, 1, 1, 2, 2, 3, 3, 3, 4],
)
# SLOW SOLUTION 1
def canonical(colum_values):
candidates = colum_values.dropna().unique()
if len(candidates) == 1:
return candidates[0]
else:
return np.nan
solution_1 = df.groupby(df.index).aggregate(canonical)
# SLOW & UGLY SOLUTION 2
def solve_2(df):
df = df.copy()
for dupe in df.index[df.index.duplicated(keep="first")]:
for column in df.columns:
values = df[df.index == dupe][column]
if len(values.dropna().unique()) == 1:
df.loc[df.index == dupe, column] = values.dropna().iloc[0]
else:
df.loc[df.index == dupe, column] = np.nan
# duplicate rows should all now share the same value, so just keep one.
df.drop_duplicates(keep="first", inplace=True)
return df
solution_2 = solve_2(df)
寻找对这些的任何改进,以在大型数据集上获得更好的性能。
谢谢。
解决方案
您可以group
使用数据框level=0
和聚合.first
来获取每组的第一个non-nan
值,level=0
然后.mask
是每组有多个唯一值的列中的值level=0
:
g = df.groupby(level=0)
g.first().mask(g.nunique().gt(1))
细节:
g.first()
A B C
0 1 2.0 NaN
1 2 500.0 NaN
2 3 6.0 NaN
3 300 8.0 5.0
4 400 106.0 NaN
g.nunique().gt(1)
A B C
0 False False False
1 True False False
2 True False False
3 False False False
4 False False False
结果:
A B C
0 1.0 2.0 NaN
1 NaN 500.0 NaN
2 NaN 6.0 NaN
3 300.0 8.0 5.0
4 400.0 106.0 NaN
推荐阅读
- javascript - TypeError [ERR_INVALID_ARG_TYPE]:“块”参数必须是字符串类型或 Buffer 的实例。收到一个对象实例
- c++ - 修改矩阵后,通过内存指针(memptr)直接访问犰狳矩阵的条目不起作用
- c# - 警告“消息模板不是编译时间常数”
- flutter - SVG 图像加载前的加载图标
- python - 访问和更改模块级变量
- excel - 将多个excel文件中的特定值复制到一个表中
- openlayers - 我可以将请求作为 imageArcgisRest 的 post 请求发送吗?开放层 6.5
- r - 在几何区域中显示缺失日期的间隙
- google-chrome - 在某些情况下,Chrome 和 Edge 中的 iframe 闪烁
- python - Keyerror:1 创建情节时