【问题标题】:Dataframe find & remove non changing values multiple fields数据框查找并删除多个字段的不变值
【发布时间】:2019-06-06 17:16:02
【问题描述】:

我正在努力处理一些数据按摩过程。 我正在考虑一种在数据框中查找和删除不变条目的最佳方法。

我有来自移动设备的信号电平数据

measDate    measLatitude    measLongitude   measCellId  measNetTypeDetail   measOperatorCode    measSignalLevel
2019-06-05 00:22:10.791     27.676038   84.177025   14603   13  42902   -97 
2019-06-05 00:22:11.806     27.676038   84.177025   14603   13  42902   -97 
2019-06-05 00:22:14.179     27.676038   84.177025   14604   13  42902   -97 
2019-06-05 00:22:14.279     27.676038   84.177025   14604   13  42902   -97 
2019-06-05 00:22:16.657     27.676038   84.177025   14604   13  42902   -97 
2019-06-05 00:22:18.904     27.676038   84.177025   14615   13  42902   -96 
2019-06-05 00:22:21.276     27.676038   84.177025   14615   13  42902   -96 
2019-06-05 00:22:23.557     27.676038   84.177025   14614   13  42902   -95 
2019-06-05 00:22:24.796     27.676038   84.177025   14603   10  42902   -96 
2019-06-05 00:22:26.768     27.676038   84.177025   14603   10  42902   -96 
2019-06-05 00:22:27.787     27.676038   84.177025   14603   10  42902   -96 
2019-06-05 00:22:28.802     27.676038   84.177025   14603   10  42902   -96 
2019-06-05 00:22:31.803     27.676038   84.177025   14603   10  42902   -96 
2019-06-05 00:22:33.799     27.676038   84.177025   14603   10  42902   -96 

所以基本上是 signalLevel 和一些相关的数据 + 时间戳

我需要做的是通过以下方式过滤数据:

  • 如果过去 n 个样本的信号电平没有变化(例如,n=3 个样本)
  • 如果其他值也没有变化
  • 过滤掉数据。

所以最后我希望在一行中有最多 n 个相同的样本。

WINDOW N=3 的预期结果

measDate    measLatitude    measLongitude   measCellId  measNetTypeDetail   measOperatorCode    measSignalLevel
2019-06-05 00:22:10.791     27.676038   84.177025   14603   13  42902   -97 
2019-06-05 00:22:11.806     27.676038   84.177025   14603   13  42902   -97 
2019-06-05 00:22:14.179     27.676038   84.177025   14604   13  42902   -97 
2019-06-05 00:22:18.904     27.676038   84.177025   14615   13  42902   -96 
2019-06-05 00:22:21.276     27.676038   84.177025   14615   13  42902   -96 
2019-06-05 00:22:23.557     27.676038   84.177025   14614   13  42902   -95 
2019-06-05 00:22:24.796     27.676038   84.177025   14603   10  42902   -96 
2019-06-05 00:22:26.768     27.676038   84.177025   14603   10  42902   -96 
2019-06-05 00:22:27.787     27.676038   84.177025   14603   10  42902   -96

经过一些测试,我来到了这段代码。我尝试通过检查每列窗口内的唯一值(这里窗口大小=3)来检查是否有任何列值发生了变化,然后我总结是否有任何列发生了变化,那么我需要保留它

RadioSmall = RadioMeasAll.loc[:,['measLatitude','measLongitude','measCellId','measNetTypeDetail','measOperatorCode','measCid','measLac','measSignalLevel','cellArfcn']].copy()

def f(x):
    y = x[~np.isnan(x)]
    if len(np.unique(y)) > 1:
        return 1
    else:
        return 0

a = RadioSmall.rolling(window=3, min_periods=1).apply(f,raw=True)
a['sum']=a.sum(axis=1)
b = pd.DataFrame(index=a.index)
b['filtering'] = a['sum']
df_filtered =  b.query('filtering>0')

RadioMeasAll.join(df_filtered)

我觉得很丑。

感谢您的帮助!

【问题讨论】:

标签: python pandas dataframe filtering


【解决方案1】:
import numpy as np

cols_to_compare = df.columns.drop(['measDate'])  # Columns where the values will be compared
window_size = 3

has_change = df[cols_to_compare].diff().any(axis=1)
df = df[has_change.rolling(window_size).apply(np.any, raw=True).fillna(1, downcast="bool")]

【讨论】:

    【解决方案2】:

    我相信我现在明白你的目标了。

    df.reset_index(drop=False) # I want to opearte on integer indices
    a = df.index[(df[columns] == df[columns].shift()).all(axis=1)]
    

    a 是一个数组,其中包含连续行的索引,其 columns 的值等于下一行(它忽略了第一次出现)。

    现在我们应该将其拆分为连续索引的子集,(来自 answer 的想法)

    duplicate_groups = np.split(a, np.where(np.diff(a) != 1)[0] + 1)
    

    duplicate_groups 现在包含连续索引的数组。您现在可以过滤比 N 长的连续重复,比如N = 5

    [arr for arr in duplicate_groups if len(arr) > 4] # 4 b/c we ommitted FIRST occurrence
    

    尝试在您的数据上运行它,看看它是否能解决您的问题。

    【讨论】:

    • 我理解 columns 是要检查的列数组。但什么是 id_ ?我用我的示例代码和可复制集编辑了我的帖子
    • 抱歉,id_ 应该是 a
    • 运行前两行后,a 包含什么?
    • a 返回空 [] columns = ['measLatitude','measLongitude','measCellId','measNetTypeDetail','measOperatorCode','measLac','measSignalLevel','cellArfcn'] df.reset_index(drop=False) a = df.index[(df[columns] == df[columns].shift()).all(axis=1)]
    • 这些列中的任何一个是浮动的吗?更改您的 columns 变量,使其只有 measSignalLevel 然后查看,然后添加更多列并检查哪一列使 a 为空
    【解决方案3】:

    我会使用与原始数据帧共享相同索引的临时数据帧来计算连续值组、它们的大小和行在其组中的排名。

    然后我只会在原始数据框中保留在窗口下方排名的行:

    tmp = pd.DataFrame(index=df.index)                     # tmp dataframe with same index
    tmp['dup'] = df[df.columns[1:].tolist()].duplicated()  # duplicated rows (except for datetime)
    # define groups of consecutive rows
    tmp.loc[~tmp['dup'],'change'] = 1               
    tmp['group'] = tmp['change'].cumsum()
    tmp['group'].fillna(method='ffill', inplace=True)
    
    # compute ranks in groups 
    tmp['rank'] = tmp.groupby('group').cumcount()
    
    # extract a filtered dataframe
    filtered = df.loc[tmp['rank'] < 3]
    

    它按预期给出:

                      measDate  measLatitude  measLongitude  measCellId  measNetTypeDetail  measOperatorCode  measSignalLevel
    0  2019-06-05 00:22:10.791     27.676038      84.177025       14603                 13             42902              -97
    1  2019-06-05 00:22:11.806     27.676038      84.177025       14603                 13             42902              -97
    2  2019-06-05 00:22:14.179     27.676038      84.177025       14604                 13             42902              -97
    3  2019-06-05 00:22:14.279     27.676038      84.177025       14604                 13             42902              -97
    4  2019-06-05 00:22:16.657     27.676038      84.177025       14604                 13             42902              -97
    5  2019-06-05 00:22:18.904     27.676038      84.177025       14615                 13             42902              -96
    6  2019-06-05 00:22:21.276     27.676038      84.177025       14615                 13             42902              -96
    7  2019-06-05 00:22:23.557     27.676038      84.177025       14614                 13             42902              -95
    8  2019-06-05 00:22:24.796     27.676038      84.177025       14603                 10             42902              -96
    9  2019-06-05 00:22:26.768     27.676038      84.177025       14603                 10             42902              -96
    10 2019-06-05 00:22:27.787     27.676038      84.177025       14603                 10             42902              -96
    

    注意:如果在原始数据框中,日期时间是索引而不是列,则重复项的定义将更改为:

    tmp['dup'] = df.duplicated()  # duplicated rows 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-07-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-12
      • 2022-01-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多