从数据框中的组中删除具有特定列

时间:2018-05-15 07:38:51

标签: python pandas dataframe

我在csv文件中有一个数据集。我使用pandas作为数据帧导入它。然后,我根据我命名为Vf的列来命令我的数据从最小到最大。

从这里开始我的代码尝试: 将排序的数据帧(DF)分组为11个组。 计算每组中相应的最小值和最大值之间的差异。 迭代每个组并检查任何组的最小值和最大值之间的差异是否大于0.2。 如果任何组满足此条件,我希望代码从原始数据帧中删除包含该组最小值的数据行。 然后再次对数据帧进行排序和分组,减去该行。 再次遍历每个组,检查最小值和最大值之间的差异。 它应该继续这样做,直到它经过每个组,并发现它们中没有一个在最小值和最大值之间有差异大于0.2。

就我所知,我现在的代码就这么做了。但是当我想要它时它不会停止,即当所有组的最小值和最大值之间的差异小于0.2时,它不会停止。此外,此时它实际上似乎将行添加回原始数据帧。

这是代码。请注意,我已将其设置为仅浏览数据中的前两组。还要注意我的for循环中的行要求它打印语句和排序数据帧的形状。这都是为调试目的提供信息。

def celling():
import numpy as np
import pandas as pd
Data = input("Name of File: ")
DF = pd.read_csv("Y:\CHRIS\{}.csv".format(Data), skiprows = 20, names = ["Serial","Bin","Ir","Vf"])

def sort(Data):
    SortedDF = Data.sort_values(by='Vf')
    GroupedDF = SortedDF.groupby(np.arange(len(SortedDF))//11)
    GroupMax = GroupedDF["Vf"].max()
    GroupMin = GroupedDF["Vf"].min()
    GroupDiff = GroupMax - GroupMin
    GroupMinIndices = GroupedDF["Vf"].idxmin()
#sort(DF)
    for i in range(2):

        if GroupDiff[i] > 0.2:
            DF = Data[Data.index != GroupMinIndices[i]]
            print("Group {} was bad.".format(i))
            print(SortedDF.shape)
            sort(DF)
        else:
            print("Group {} is good.".format(i))
        print(SortedDF.shape)
sort(DF)

以下是原始数据框的示例:

        Serial  Bin       Ir     Vf
    0        1  1.0  0.00161  170.7
    1        2  1.0  0.00157  173.3
    2        3  1.0  0.00169  171.0
    3        4  1.0  0.00145  172.7
    4        5  1.0  0.00170  171.4
    5        6  1.0  0.00160  172.6
    6        7  1.0  0.00180  172.4
    7        8  1.0  0.00169  172.1
    8        9  1.0  0.00147  170.9
    9       10  1.0  0.00151  172.3
    10      11  1.0  0.00142  171.8
    11      12  1.0  0.00168  171.5

以下是按Vf排序的数据框示例:

    Serial  Bin       Ir     Vf
477    478  1.0  0.00180  170.0
359    360  1.0  0.00139  170.1
247    248  1.0  0.00197  170.1
575    576  1.0  0.00159  170.2
267    268  1.0  0.00178  170.2
178    179  1.0  0.00277  170.3
82      83  1.0  0.00145  170.3
574    575  1.0  0.00162  170.3
97      98  1.0  0.00190  170.3
399    400  1.0  0.00172  170.4
21      22  1.0  0.00166  170.4
67      68  1.0  0.00176  170.5
103    104  1.0  0.00154  170.5
553    554  1.0  0.00169  170.5
533    534  1.0  0.00167  170.5
177    178  1.0  0.00160  170.5
35      36  1.0  0.00150  170.5
186    187  1.0  0.00165  170.5
363    364  1.0  0.00172  170.6
487    488  1.0  0.00159  170.6

理想情况下,代码应该做的是检查此示例的前11行,注意11中的最大值和最小值之间的差值大于0.2,并从第一行中删除具有最小值的行11,在这种情况下,将是序列号为no的行。 478.然后它应该重新组合数据,其中上面样本中的第2-12行现在构成第一组11.然后应该注意到最小/最大差异仍然大于0.2并且重新开始。下面应该是代码完成后上面样本中的第一组11个

178    179  1.0  0.00277  170.3
82      83  1.0  0.00145  170.3
574    575  1.0  0.00162  170.3
97      98  1.0  0.00190  170.3
399    400  1.0  0.00172  170.4
21      22  1.0  0.00166  170.4
67      68  1.0  0.00176  170.5
103    104  1.0  0.00154  170.5
553    554  1.0  0.00169  170.5
533    534  1.0  0.00167  170.5
177    178  1.0  0.00160  170.5

这是我目前代码的结果:

Group 0 was bad.
(643, 4)
Group 0 was bad.
(642, 4)
Group 0 was bad.
(641, 4)
Group 0 was bad.
(640, 4)
Group 0 was bad.
(639, 4)
Group 0 is good.
(638, 4)
Group 1 was bad.
(638, 4)
Group 0 is good.
(637, 4)
Group 1 was bad.
(637, 4)
Group 0 is good.
(636, 4)
Group 1 was bad.
(636, 4)
Group 0 is good.
(635, 4)
Group 1 was bad.
(635, 4)
Group 0 is good.
(634, 4)
Group 1 was bad.
(634, 4)
Group 0 is good.
(633, 4)
Group 1 is good.
(633, 4)
(634, 4)
(635, 4)
(636, 4)
(637, 4)
(638, 4)
(639, 4)
Group 1 is good.
(639, 4)
(640, 4)
Group 1 is good.
(640, 4)
(641, 4)
Group 1 is good.
(641, 4)
(642, 4)
Group 1 is good.
(642, 4)
(643, 4)
Group 1 is good.
(643, 4)
(643, 4)

注意当它读取组0的max和min之间的差值大于0.2时,它如何继续删除行。然后它继续进行到第1组。当它读取第1组中的最大/最小差异大于0.2时,它会删除该行并返回到for循环的开头(我知道这不是很有效)。但是,请注意理论上它应该在读取时立即停止,而第0组是好的,然后第1组是好的,但它没有。请注意,在它读取后它们都很好,它似乎开始在数据帧中添加行。

如果有人能够解释我的代码为什么会这样做,或者解释我的代码在做什么,如果它没有这样做,那将非常感激。注意,我是python的新手,所以要善良! :)

1 个答案:

答案 0 :(得分:1)

这是一个棘手的问题,所以让我们重新开始吧。

    使用列Vf
  1. 排序数据
  2. 群组连续11行&找到最小 - 最大扩展超过0.2的第一组。
  3. 拆分数据分为两部分,从这一组开始,第一部分是部分,第二部分是错误并要求从一开始就删除行。
  4. 错误部分的开头
  5. 删除行,直到VfVf.shift(-10)之间的差异不超过0.2
  6. 重复这些步骤(group-split-remove),直到拆分有空的坏部分
  7. 加入所有好的部分以获得最终结果
  8. (可选)将组ID分配给最终结果
  9. 创建示例排序数据框:

    df = pd.read_table(io.StringIO("""    Serial  Bin       Ir     Vf
    477    478  1.0  0.00180  170.0
    359    360  1.0  0.00139  170.1
    247    248  1.0  0.00197  170.1
    575    576  1.0  0.00159  170.2
    267    268  1.0  0.00178  170.2
    178    179  1.0  0.00277  170.3
    82      83  1.0  0.00145  170.3
    574    575  1.0  0.00162  170.3
    97      98  1.0  0.00190  170.3
    399    400  1.0  0.00172  170.4
    21      22  1.0  0.00166  170.4
    67      68  1.0  0.00176  170.5
    103    104  1.0  0.00154  170.5
    553    554  1.0  0.00169  170.5
    533    534  1.0  0.00167  170.5
    177    178  1.0  0.00160  170.5
    35      36  1.0  0.00150  170.5
    186    187  1.0  0.00165  170.5
    363    364  1.0  0.00172  170.6
    487    488  1.0  0.00159  170.6"""), sep='\s+')
    

    以下是帮助函数:

    def grouper(frame):
        return np.arange(len(frame)) // 11
    
    def remove(frame): 
        return (
            (frame.Vf.shift(-10).fillna(frame.Vf.max()) - frame.Vf) < 0.2
        ).cumsum() > 0
    
    def split_df(frame): 
        return frame.groupby(
            grouper(frame)
        ).Vf.transform(
            lambda x: (x.max() - x.min()) > 0.2
        ).cumsum() > 0
    

    column.cumsum() > 0其中column有一个布尔类型,在遇到第一个真值后过滤所有行,包括行为true。

    以下函数实现上述递归逻辑(借助上面定义的一些辅助函数)

    def group_split_remove(frame):
        temp = frame[split_df(frame)]
        if len(temp) == 0:
            return frame
        return pd.concat([frame[~split_df(frame)], group_split_remove(temp[remove(temp)])])
    

    现在,python中的递归并不总是最好的策略,因此,如果上述速度不够快或达到最大递归深度,则将其重新表示为while循环。但是,我相信递归公式在这种情况下更具可读性

    使用您的样本(已排序)数据,group_split_remove(df)返回以下数据框:

         Serial  Bin       Ir     Vf
    178     179  1.0  0.00277  170.3
    82       83  1.0  0.00145  170.3
    574     575  1.0  0.00162  170.3
    97       98  1.0  0.00190  170.3
    399     400  1.0  0.00172  170.4
    21       22  1.0  0.00166  170.4
    67       68  1.0  0.00176  170.5
    103     104  1.0  0.00154  170.5
    553     554  1.0  0.00169  170.5
    533     534  1.0  0.00167  170.5
    177     178  1.0  0.00160  170.5
    35       36  1.0  0.00150  170.5
    186     187  1.0  0.00165  170.5
    363     364  1.0  0.00172  170.6
    487     488  1.0  0.00159  170.6
    

    如您所见,前11行完全符合您的预期输出。

    最后一个可选步骤是分配一个group_id,可以按如下方式完成:

    res['group_id'] = grouper(res)