我要收集许多天的数据,而不是每天都要填写,我可以选择说一天中的数据实际上应该是另一天的重复。我想将现有数据框中的某些行重复到指定为重复的日子。我有一列指示当前日期是从哪一天开始重复,但我陷入了错误。
我已经找到了基于列值重复行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'])
答案 0 :(得分:0)
# Start with Valdi_Bo's expanded example data
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'])
# Convert Day to integer data type
df['Day'] = df['Day'].astype(int)
# Spread repeat_tag values into all rows of tagged day
df['repeat_tag'] = df.groupby('Day')['repeat_tag'].ffill()
# Within each day, assign a number to each row
df['obs'] = df.groupby('Day').cumcount()
# Self-join
filler = (pd.merge(df, df,
left_on=['repeat_tag', 'obs'],
right_on=['Day', 'obs'])
.set_index(['Day_x', 'obs'])['Data_y'])
# Fill missing data
df = df.set_index(['Day', 'obs'])
df.loc[df['Data'].isnull(), 'Data'] = filler
df = df.reset_index()
df
Day obs Data repeat_tag
0 1 0 51.0 NaN
1 1 1 52.0 NaN
2 1 2 53.0 NaN
3 2 0 61.0 NaN
4 2 1 62.0 NaN
5 2 2 63.0 NaN
6 3 0 51.0 1.0
7 3 1 52.0 1.0
8 3 2 53.0 1.0
9 4 0 61.0 2.0
10 4 1 62.0 2.0
11 4 2 63.0 2.0
答案 1 :(得分:0)
我稍微扩展了您的测试数据:
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'])
详细信息:
我假设 repeat_tag 的非空值只能放在一个 观察“目标”日。
我还添加了 obsNo 列以标识特定日期的观察值:
df['obsNo'] = df.groupby('Day').cumcount().add(1);
(稍后需要)。
实际处理的第一步是生成 replDays 表,其中 Day 列是目标日, 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 。因此,要获取 string 类型(与 Day 相比) 必须转换:
结果是:
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
如您所见:
最后一部分包括以下步骤:
代码是:
res = df.copy().set_index(['Day', 'obsNo'])
res.update(replData)
res.reset_index(inplace=True)
如果需要,还可以删除 obsNo 列。
以及有关 Peter 解决方案的评论: 如果源数据包含任意一天的不同值,则其代码将失败 与 InvalidIndexError 一起使用,可能是由于缺少 在特定日期内的个人观察。 这证实了我添加 obsNo 列的想法是有效的。