【问题标题】:Pandas: Insert missing row data and iterate with conditions within groupsPandas:插入缺失的行数据并使用组内的条件进行迭代
【发布时间】:2020-10-26 01:32:03
【问题描述】:

我有一个数据框,需要插入缺失的行数据。这是数据框:

df = pd.DataFrame({
    'name': ['Jim', 'Jim', 'Jim', 'Jim', 'Mike', 'Mike', 'Mike', 'Mike', 'Mike',
           'Polo', 'Polo', 'Polo', 'Polo', 'Tom', 'Tom', 'Tom', 'Tom'],
    'From_num': [80, 68, 751, 'Started', 32, 68, 126, 49, 'Started', 105, 68, 76, 'Started', 251, 49, 23, "Started"],
    'To_num':[99, 80, 68, 751, 105, 32, 68, 126, 49, 324, 105, 114, 76, 96, 115, 49, 23],
})
    name From_num  To_num
0    Jim       80      99
1    Jim       68      80
2    Jim      751      68
3    Jim  Started     751
4   Mike       32     105
5   Mike       68      32
6   Mike      126      68
7   Mike       49     126
8   Mike  Started      49
9   Polo      105     324
10  Polo       68     105
11  Polo       76     114 #Missing record between line 10 and 11
12  Polo  Started      76
13   Tom      251      96
14   Tom       49     115 # Missing record between 13 and 14
15   Tom       23      49
16   Tom  Started      23

每组(人名)的数据记录在每一行的'From_num'到'To_num'是连续的,并且从下到上对齐,例如Jim: 'Started' -> 751, 751->68, 68->80, 80->99;迈克的模式相同。但是 Polo ad Tom 有一些缺失的数据,例如我希望在第 10 行和第 11 行之间插入一行: 114 -> 105 以使整个记录是连续的。和 Tom 一样,在 13 和 14 之间插入一行:115 -> 251。我尝试使用循环条件进行编码,但失败了,所以如果您有任何想法,请提供帮助。请不要直接插入那些丢失的记录,因为这是一个简单的例子。非常感谢您的帮助!希望问题很清楚。预期结果如下:

df_expected:
    name From_num  To_num
0    Jim       80      99
1    Jim       68      80
2    Jim      751      68
3    Jim  Started     751
4   Mike       32     105
5   Mike       68      32
6   Mike      126      68
7   Mike       49     126
8   Mike  Started      49
9   Polo      105     324
10  Polo       68     105
11  Polo      114      68 # New Inserted line
12  Polo       76     114
13  Polo  Started      76
14   Tom      251      96
15   Tom      115     251 # New Inserted line
16   Tom       49     115
17   Tom       23      49
18   Tom  Started      23

【问题讨论】:

    标签: pandas loops dataframe if-statement group-by


    【解决方案1】:

    我们可以想出这个,这里的想法是使用shift获取匹配行并将不匹配行添加到原始df

    s=df.groupby('name',sort=False).From_num.shift()
    addingdata=pd.concat([s,df.drop('From_num',1)],axis=1)[df.To_num.ne(s)&s.notnull()]
    addingdata.index-=1 
    addingdata.columns=['To_num','name', 'From_num']
    df=df.append(addingdata).sort_index()
    df
        name From_num To_num
    0    Jim       80     99
    1    Jim       68     80
    2    Jim      751     68
    3    Jim  Started    751
    4   Mike       32    105
    5   Mike       68     32
    6   Mike      126     68
    7   Mike       49    126
    8   Mike  Started     49
    9   Polo      105    324
    10  Polo       68    105
    10  Polo      114     68
    11  Polo       76    114
    12  Polo  Started     76
    13   Tom      251     96
    13   Tom      115    251
    14   Tom       49    115
    15   Tom       23     49
    16   Tom  Started     23
    

    【讨论】:

      【解决方案2】:

      我们可以做到以下几点:

      1. 检查To_num 的下一行是否等于当前行From_num
      2. name 组执行此检查
      3. 对于这些行,将 To_num 替换为 From_num
      4. 最后在From_num下一个行填写To_num

      这个解决方案应该很快,因为它都是矢量化的,除了我们必须使用GroupBy.apply 检查每个组的booleans,但这是使用applyoké 场景。

      def create_masks(d):
          shift = d['To_num'].shift(-1)
          m1 = d['From_num'].ne(shift)
          m2 = shift.notna()
          
          return m1 & m2
      
      
      def create_rows(d):
          bools =  d.groupby('name').apply(create_masks).reset_index(drop=True)
          vals = d[bools].copy()
          vals['To_num'] = vals['From_num']
          vals.loc[:, 'From_num'] = d.loc[bools.shift().fillna(False), 'To_num'].to_numpy()
          d = d.append(vals).sort_index().reset_index(drop=True)
          
          return d
      
      df = create_rows(df)
      

      输出

      
          name From_num To_num
      0    Jim       80     99
      1    Jim       68     80
      2    Jim      751     68
      3    Jim  Started    751
      4   Mike       32    105
      5   Mike       68     32
      6   Mike      126     68
      7   Mike       49    126
      8   Mike  Started     49
      9   Polo      105    324
      10  Polo       68    105
      11  Polo      114     68
      12  Polo       76    114
      13  Polo  Started     76
      14   Tom      251     96
      15   Tom      115    251
      16   Tom       49    115
      17   Tom       23     49
      18   Tom  Started     23
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-02-23
        • 2015-10-01
        • 1970-01-01
        • 1970-01-01
        • 2019-04-10
        • 2021-12-06
        • 2022-01-19
        • 2013-08-24
        相关资源
        最近更新 更多