基于列值重复数据帧的部分

2024-05-16 08:56:48 发布

您现在位置:Python中文网/ 问答频道 /正文

我收集了很多天的数据,而不是每天填写,我可以选择说,一天的数据应该是另一天的重复。我想将现有数据帧中的一些行重复到指定为repeats的日期中。我有一个列,指出哪一天是当前的一天是重复,但我陷入了错误。你知道吗

我已经找到了基于列值将行重复n次的方法,但是我正在尝试使用列作为索引来重复前面行中的数据。你知道吗

我想用“Repeat”列作为索引,将第1天的“Data”列的一部分复制到第3天的“Data”列。我想在更多不同的日子里这样做。你知道吗

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']) 

Tags: columns数据方法dataframedfdata错误np
2条回答

设置

# 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

我稍微扩展了你的测试数据:

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'天和第'4'天,从第'2'天开始。你知道吗

我假设repeat\u tag的非空值只能放在一个 观察“目标”日。你知道吗

我还添加了obsNo列,以确定特定日期内的观察结果:

df['obsNo'] = df.groupby('Day').cumcount().add(1);

(稍后会有必要)。你知道吗

实际处理的第一步是生成replDays表,其中Day 列是目标日期,重复标签来源日期:

replDays = df.query('repeat_tag.notnull()')[['Day', 'repeat_tag']]
replDays.repeat_tag = replDays.repeat_tag.astype(int).apply(str)

使用repeat_tag列进行一些类型操作。 由于此列包含NaN值,非空值为int,因此此列为 强制为float64。因此,要获得字符串类型(与相当) 必须转换:

  • 先到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包含日期和观察编号(两者都将是 需要适当的更新)。你知道吗

最后一部分包括以下步骤:

  • 复制dfres(结果),将索引设置为DayobsNo (更新时需要)。你知道吗
  • 使用replData中的数据更新此表。你知道吗
  • DayobsNo从索引移回“常规”列。你知道吗

代码是:

res = df.copy().set_index(['Day', 'obsNo'])
res.update(replData)
res.reset_index(inplace=True)

如果需要,还可以删除obsNo列。你知道吗

以及彼得关于解决方案的评论: 如果源数据包含任何一天不同的值,他的代码就会失败 有InvalidIndexError,可能是由于缺乏对 特定日期内的个别观察。 这证实了我添加obsNo列的想法是有效的。你知道吗

相关问题 更多 >