我要收集许多天的数据,而不是每天都要填写,我可以选择说一天的数据实际上应该是另一天的重复。我想将现有数据框中的某些行重复到指定为重复的日子。我有一列指示当前日期是从哪一天开始重复,但我陷入了错误。
我已经找到了一种基于列值将行重复n次的方法,但是我尝试使用列作为索引来重复前行的数据。
我想使用“重复”列作为索引,将第一天的“数据”列中的部分复制到第三天的“数据”列中。我想在更多不同的日子里这样做。
data = [['1', 5,np.NaN], ['1',5,np.NaN],['1',5,np.NaN], ['2', 6,np.NaN],['2', 6,np.NaN],['2', 6,np.NaN], ['3',np.NaN,1], ['3',np.NaN,np.NaN],['3', np.NaN,np.NaN]]
df = pd.DataFrame(data, columns = ['Day', 'Data','repeat_tag'])
最佳答案
我稍微扩展了您的测试数据:
data = [['1', 51, np.nan], ['1', 52, np.nan], ['1', 53, np.nan],
['2', 61, np.nan], ['2', 62, np.nan], ['2', 63, np.nan],
['3', np.nan, 1], ['3', np.nan, np.nan], ['3', np.nan, np.nan],
['4', np.nan, 2], ['4', np.nan, np.nan], ['4', np.nan, np.nan]]
df = pd.DataFrame(data, columns = ['Day', 'Data', 'repeat_tag'])
细节:
有4天的观察时间。
每个观察值都有不同的值(数据)。
为避免“单日复制”,将复制第3天的值
第1天,从第2天开始的第4天。
我假设repeat_tag的非null值只能放在一个
观察“目标”日。
我还添加了obsNo列以标识特定日期的观察结果:
df['obsNo'] = df.groupby('Day').cumcount().add(1);
(稍后需要)。
实际处理的第一步是生成replDays表,其中Day
column是目标日期,repeat_tag是源日期:
replDays = df.query('repeat_tag.notnull()')[['Day', 'repeat_tag']]
replDays.repeat_tag = replDays.repeat_tag.astype(int).apply(str)
对repeat_tag列进行了一些类型操作。
由于此列包含NaN值且非null值是int,因此此列为
强制为float64。因此,要获取字符串类型(与Day相比)
必须转换:
首先是int,要删除小数部分。
然后到str。
结果是:
Day repeat_tag
6 3 1
9 4 2
(用第1天的数据填充第3天的数据,用第2天的数据填充第4天的数据)。
下一步是生成replData表:
replData = pd.merge(replDays, df, left_on='repeat_tag', right_on='Day',
suffixes=('_src', ''))[['Day_src', 'Day', 'Data', 'obsNo']]\
.set_index(['Day_src', 'obsNo']).drop(columns='Day')
结果是:
Data
Day_src obsNo
3 1 51.0
2 52.0
3 53.0
4 1 61.0
2 62.0
3 63.0
如你看到的:
替换数据只有一列-数据(从第1天和第2天开始)。
MutliIndex包含日期和观察号(两者均为
需要进行适当的更新)。
最后一部分包括以下步骤:
将df复制到res(结果),将索引设置为Day和obsNo
(需要更新)。
使用来自replData的数据更新此表。
将Day和obsNo从索引移回“常规”列。
代码是:
res = df.copy().set_index(['Day', 'obsNo'])
res.update(replData)
res.reset_index(inplace=True)
如果需要,还可以删除obsNo列。
关于彼得的解决方案的评论:
如果源数据在任何一天中都包含不同的值,那么他的代码将失败
与InvalidIndexError一起使用,可能是由于缺少
在特定日期内的个人观察。
这证实了我添加obsNo列的想法是有效的。
关于python - 根据列值重复数据框的各个部分,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56716238/