【问题标题】:Pandas changing cell values based on another cell熊猫根据另一个单元格更改单元格值
【发布时间】:2016-07-19 11:19:54
【问题描述】:

我目前正在格式化来自两个不同数据集的数据。 其中一个数据集反映了每小时观察房间内的人数,第二个数据集是基于 5 分钟间隔生成的 wifi 日志的人数。

将这两个数据帧合并为一个后,我遇到了这样一个问题,即每个小时(如“10:00:00”)都有原始数据集的数据,但其他数据(每 5 分钟一次,如“10:47: 14") 不包括此数据。

以下是合并数据框的外观:

        room       time              con     auth  capacity    %     Count  module    size 
0       B002    Mon Nov 02 10:32:06  23      23       90       NaN    NaN   NaN        NaN`  
1       B002    Mon Nov 02 10:37:10  25      25       90       NaN    NaN   NaN        NaN`  
12527   B002    Mon Nov 02 10:00:00  NaN     NaN      90       50%    45.0  COMP30520   60`  
12528   B002    Mon Nov 02 11:00:00  NaN     NaN      90       0%     0.0   COMP30520   60`

有没有办法让我浏览数据框并从 11:00:00 找到有关“占用”、“占用计数”、“模块”和“大小”的所有信息并将其写入所有单元格是同一天,并且时间在 10:00:00 和 10:59:59 之间?

这将允许我获得每一行的所有信息,然后允许我根据“天”和“小时”收集 min()max()median()

要回答原始数据框的评论,这里有:
第一个数据框:

    time                room    module      size
0   Mon Nov 02 09:00:00 B002    COMP30190   29
1   Mon Nov 02 10:00:00 B002    COMP40660   53

第二个数据帧:

        room    time                  con   auth  capacity  %     Count
0       B002    Mon Nov 02 20:32:06   0     0     NaN       NaN   NaN
1       B002    Mon Nov 02 20:37:10   0     0     NaN       NaN   NaN
2       B002    Mon Nov 02 20:42:12   0     0     NaN       NaN   NaN
12797   B008    Wed Nov 11 13:00:00   NaN   NaN   40        25    10.0
12798   B008    Wed Nov 11 14:00:00   NaN   NaN   40        50    20.0
12799   B008    Wed Nov 11 15:00:00   NaN   NaN   40        25    10.0

这就是这两个数据框合并在一起的方式:

DFinal = pd.merge(DF, d3, left_on=["room", "time"], right_on=["room", "time"], how="outer", left_index=False, right_index=False)

对此的任何帮助将不胜感激。

非常感谢,

-罗曼

【问题讨论】:

  • 您希望输出的前两行是:0 B002 Mon Nov 02 10:32:06 23 23 90 90 0% COMP30520 601 B002 Mon Nov 02 10:37:10 25 25 90 0% COMP30520 60? “时间”列的格式是什么? (使用df.time查看)
  • 你能提供你到目前为止所做的事情吗?您是如何执行合并的?您希望以更清晰的方式获得什么预期结果?
  • 嗨@sirfz,这是我合并两个数据帧的方法: DFinal = pd.merge(DF, d3, left_on=["room", "time"], right_on=["room", "time"], how="outer", left_index=False, right_index=False)
  • @RomainD:请通过编辑您的问题将此代码 sn-p 添加到您的问题中。
  • 嗨@danielhadar,我想将所有记录保留在最终数据框中,以便生成包含基于日期和小时的 min()、max() 和 median() 值的数据库表. 'time' 列也是一个对象并遵循这种格式( %a %b %d $H:%M:%S )

标签: python python-3.x pandas dataframe


【解决方案1】:

从哪里开始:

b = df[(df['time'] > X) & (df['time'] < Y)]

选择时间 X 和 Y 内的所有元素

然后

df.loc[df['column_name'].isin(b)]

为您提供所需的行(即 - 在 X 和 Y 之间),您可以根据需要进行分配。 我认为您希望将所选行的值分配给行号 X 的值?

希望对您有所帮助。

请注意,这些功能是来自
的剪切和粘贴作业 [1] Filter dataframe rows if value in column is in a set list of values
[2]Select rows from a DataFrame based on values in a column in pandas

【讨论】:

    【解决方案2】:

    如果我理解正确,您想用给定小时内可用的相应最近数据点填充合并数据框中的所有缺失值。过去我在本质上做了类似的事情,使用 pandas.cut 的变量作为时间序列,但我似乎找不到它,反正它不是很好。

    虽然我不完全确定,但 pandas 数据框的 fillna 方法可能就是您想要的 (docs here)。

    让您的两个数据框命名为df_hourdf_cinq,您可以这样合并它们:

    df = pd.merge(df_hour, df_cinq, left_on=["room", "time"], right_on=["room", "time"], how="outer", left_index=False, right_index=False)
    

    然后您将索引更改为时间并对其进行排序:

    df.set_index('time',inplace=True)
    df.sort_index(inplace=True)
    

    fillna 方法有一个名为“方法”的选项,它可以具有这些值 (2):

       Method                 Action  
     pad / ffill          Fill values forward  
     bfill / backfill     Fill values backward  
     nearest              Fill from the nearest index value  
    

    用它做前向填充(即缺失值用帧中的前一个值填充):

    df.fillna(method='ffill', inplace=True)
    

    这对您的数据的问题在于,属于 5 分钟观察的非工作时间的所有缺失数据都将被过时的数据点填充。您可以使用limit 选项来限制要填充的连续数据点的数量,但我不知道它是否对您有用。

    这是我作为玩具示例编写的完整脚本:

    import pandas as pd
    import random
    
    
    hourly_count = 8 #workhours 
    cinq_count = 24 * 12 # 1day
    
    hour_rng = pd.date_range('1/1/2016-09:00:00', periods = hourly_count, freq='H')
    cinq_rng = pd.date_range('1/1/2016-00:02:53', periods = cinq_count,
                                freq='5min')
    
    roomz = 'room0 room1 secretroom'.split()
    
    hourlydata = {'col1': [], 'col2': [], 'room': []}
    for i in range(hourly_count):
        hourlydata['room'].append(random.choice(roomz))
        hourlydata['col1'].append(random.random())
        hourlydata['col2'].append(random.randint(0,100))
    
    
    cinqdata = {'col3': [], 'col4': [], 'room': []}
    frts = 'apples oranges peaches grapefruits whatmore'.split()
    vgtbls = 'onion1 onion2 onion3 onion4 onion5 onion0'.split()
    for i in range(cinq_count):
        cinqdata['room'].append(random.choice(roomz))
        cinqdata['col3'].append(random.choice(frts))
        cinqdata['col4'].append(random.choice(vgtbls))
    
    hourlydf = pd.DataFrame(hourlydata)
    hourlydf['time'] = hour_rng
    cinqdf = pd.DataFrame(cinqdata)
    cinqdf['time'] = cinq_rng
    
    df = pd.merge(hourlydf, cinqdf, left_on=['room','time'], right_on=['room',
        'time'], how='outer', left_index=False, right_index=False)
    
    df.set_index('time',inplace=True)
    df.sort_index(inplace=True)
    df.fillna(method='ffill', inplace=True)
    print(df['2016-1-1 09:00:00':'2016-1-1 17:00:00'])
    

    【讨论】:

      【解决方案3】:

      其实我可以通过以下方式解决这个问题:

      首先:使用“时间”功能分区来生成两个额外的列,一个用于“时间”中显示的,另一个用于“时间”中显示的小时 “时间”栏目。 我使用 lambda 函数来获取这些列:

      df['date'] = df['date'].map(lambda x: x[10:-6])
      df['time'] = df['time'].map(lambda x: x[8:-8])
      

      基于这两个新列,我修改了数据框的合并方式。

      这是我用来修复它的代码:

      dataframeFinal = pd.merge(dataframe1, dataframe2, left_on=["room", "date", "hour"],
                      right_on=["room", "date", "hour"], how="outer",
                      left_index=False, right_index=False, copy=False)
      

      在这次合并之后,我最终得到了重复的时间列(“time_y”和“time_x”)。
      所以我将 NaN 值替换如下:

      dataframeFinal.time_y.fillna(dataframeFinal.time_x, inplace=True)
      

      现在“time_y”列包含所有时间值,不再是 NaN。 我不需要“time_x”列,所以我将其从数据框中删除

      dataframeFinal = dataframeFinal.drop('time_x', axis=1)
      

      【讨论】: