【问题标题】:How can I fill missing data in my dataframe faster for a big dataset, and without a SettingWithCopyWarning?对于大数据集,如何在没有 SettingWithCopyWarning 的情况下更快地填充数据框中的缺失数据?
【发布时间】:2021-08-11 14:49:32
【问题描述】:

我有一个数据框,其中包含每天和每个位置的人数。在没有任何缺失数据的情况下,我预计每天有 4 行:2 个位置和 2 个性别。一些数据缺失,应该用平均计数代替,但前提是该位置在前一天有该性别的数据。

如果数据丢失超过 1 天,我认为应该没有数据。因此,例如在我的示例数据框中:第 2 天,位置 X,性别 F 应该被填写,因为第 1 天,位置 X,性别 F 存在。但是第 4 天,位置 Y,性别 F 必须保持空白,因为第 3 天,位置 Y,性别 F 不存在。

  • 下面的代码适用于这个小数据帧,但对于我的大数据集来说真的很慢。有没有办法更快地做到这一点?
  • 在这种情况下我可以避免 SettingWithCopyWarnings 吗?
import pandas as pd
import numpy as np
import random

data = pd.DataFrame({'day': [1,1,2,3,3,4,5,1,2], 
                     'location': ['X', 'X', 'X', 'X', 'X', 'X', 'X', 'Y', 'Y'],
                     'gender': ['F', 'M', 'M','F', 'M','F', 'F','F','F'],
                     'count': random.sample(range(10, 30), 9)})

print(data.sort_values('day').reset_index(drop=True))


    day location    gender  count
0   1   X   F   17
1   1   X   M   10
2   1   Y   F   12
3   2   X   M   20
4   2   Y   F   15
5   3   X   F   24
6   3   X   M   29
7   4   X   F   11
8   5   X   F   14


data2 = pd.DataFrame()
for e, today in enumerate(list(set(data['day'].sort_values()))[1:]):
  yesterday = (list(set(data['day'].sort_values()))[e])
  today_df = data[(data['day']==today)].set_index(['location','gender'])
  yesterday_df = data[(data['day']==yesterday)].set_index(['location','gender'])

  today_missing = [[i[0],i[1]] for i in yesterday_df.index if i not in today_df.index]

  for i in today_missing:
    new_row = data[(data['day']==yesterday) & (data['location']==i[0]) & (data['gender']==i[1])]
    new_row['day'] = today
    new_row['count'] = int(np.mean(data['count'][(data['location']==i[0]) & (data['gender']==i[1])]))

    data2 = data2.append(new_row, ignore_index=True)

data = data.append(data2).sort_values('day').reset_index(drop=True)
print(data)

    day location    gender  count
0   1   X   F   17
1   1   X   M   10
2   1   Y   F   12
3   2   X   M   20
4   2   Y   F   15
5   2   X   F   16
6   3   X   F   24
7   3   X   M   29
8   3   Y   F   13
9   4   X   F   11
10  4   X   M   19
11  5   X   F   14

【问题讨论】:

  • 嗨@Karen。解决方案成功了吗?如果是这样并且您愿意,请标记它,以便可以将此问题标记为已解决。谢谢!
  • 谢谢,是的,这个解决方案非常完美!

标签: python pandas


【解决方案1】:

一种解决方案是重新生成位置、性别和日期的可能组合

df = data.set_index(['location', 'gender', 'day'])
         .reindex(pd.MultiIndex.from_product(
          [['X', 'Y'], ['F', 'M'], range(1, 8)],
          names=['location', 'gender', 'day']))

                     count
location gender day       
X        F      1     17.0
                2      NaN
                3     24.0
                4     11.0
                5     14.0
                6      NaN
                7      NaN
         M      1     10.0
                2     20.0
                3     29.0
                4      NaN
                5      NaN
                6      NaN
                7      NaN
Y        F      1     12.0
                2     15.0
                3      NaN
                4      NaN
                5      NaN
                6      NaN
                7      NaN
         M      1      NaN
                2      NaN
                3      NaN
                4      NaN
                5      NaN
                6      NaN
                7      NaN

1:解决方案填充每个location, gender 组的平均值

df.groupby(['location', 'gender']).transform(lambda x: x.fillna(x.mean(), limit=1)).dropna()

                         count
location gender day           
X        F      1    17.000000
                2    16.500000
                3    24.000000
                4    11.000000
                5    14.000000
         M      1    10.000000
                2    20.000000
                3    29.000000
                4    19.666667
Y        F      1    12.000000
                2    15.000000
                3    13.500000

2:解决方案在天之间线性插值

另一种解决方案是在 [location, gender] 组内的天数之间进行插值,填充时间限制为 1 天:

df.interpolate(level=['location', 'gender'], limit=1).dropna()

                         count
location gender day           
X        F      1    17.000000
                2    20.500000
                3    24.000000
                4    11.000000
                5    14.000000
                6    12.666667
         M      1    10.000000
                2    20.000000
                3    29.000000
                4    25.600000
Y        F      1    12.000000
                2    15.000000
                3    15.000000

您可以通过 df.reset_index() 删除多索引。希望有用。

【讨论】:

  • 谢谢!如果数据丢失超过 1 天,我认为应该没有数据。所以我不想在一天后用 NaN 填充 NaN。 Y, F, 3 应该填写,但 Y, F, 4 应该留空。我会在我的问题中更清楚地说明这一点!
  • @Karen 刚刚编辑了答案,希望对您有所帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-20
  • 1970-01-01
  • 1970-01-01
  • 2018-12-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多