【问题标题】:Creating new columns with Pandas df.apply使用 Pandas df.apply 创建新列
【发布时间】:2021-01-22 07:56:54
【问题描述】:

我有一个巨大的 NetFlow 数据库,(它包含时间戳、源 IP、目标 IP、协议、源和目标端口号、交换的数据包、字节等)。我想根据当前行和以前的行创建自定义属性。

我想根据当前行的源 ip 和时间戳计算新列。这就是我想要在逻辑上做的事情:

  • 获取当前行的源IP。
  • 获取当前行的时间戳。
  • 基于源 IP 和时间戳,我想获取与源 IP 匹配的整个数据帧的所有先前行,并且通信发生在最后半小时内。这非常重要。
  • 对于符合条件(源 ip 并且发生在过去半小时内)的行(在我的示例中为流),我想计算所有数据包和所有字节的总和和平均值。

One row from the dataset

相关代码片段:

df = pd.read_csv(path, header = None, names=['ts','td','sa','da','sp','dp','pr','flg','fwd','stos','pkt','byt','lbl'])

df['ts'] = pd.to_datetime(df['ts'])

def prev_30_ip_sum(ts,sa,size):
global joined
for (x,y) in zip(df['sa'], df['ts']):
    ...
return sum

df['prev30ipsumpkt'] = df.apply(lambda x: prev_30_ip_sum(x['ts'],x['sa'],x['pkt']), axis = 1)

我知道可能有更好、更有效的方法来做到这一点,但遗憾的是我不是最好的程序员。

谢谢。

【问题讨论】:

  • df = pd.read_csv(path, header = None, names=['te','td','sa','da','sp','dp','pr','flg','fwd','stos','pkt','byt','lbl']) 在这一行中我没有看到任何'ts'。但是您正在将它转换为另一行中的日期时间。 te 和 td 在数据框中代表什么?
  • td 是持续时间,te 应该是建立的时间。基本上是时间戳。我编辑了 sn-p,以保持一致。对不起。
  • 感谢@chad。所以让我知道我是否正确。您想找出所有具有相同源地址的行,并且时间戳应该在最近 30 分钟内吗?
  • 您说“我想获取与源 IP 匹配的整个数据帧的所有先前行,并且通信发生在最后半小时内。”。它真的需要是“之前的行”,还是您正在寻找的是您应该考虑的行的时间戳应该发生在当前时间戳之前的 30 分钟内?
  • 这完全正确@PunitVara。我想根据这些行创建新列(数据集的新属性)。所以我想为数据集中的每一行计算这个。

标签: python pandas dataframe netflow


【解决方案1】:

内嵌文档

from datetime import timedelta

def fun(df, i):
  # Current timestamp
  current = df.loc[i, 'ts']
  # timestamp of last 30 minutes
  last = current - timedelta(minutes=30)
  # Current IP
  ip = df.loc[i, 'sa']
  
  # df matching the criterian
  adf = df[(last <= df['ts']) & (current > df['ts']) & (df['sa'] == ip)]

  # Return sum and mean
  return adf['pkt'].sum(), adf['pkt'].mean()

# Apply the fun over each row
result = [fun(df, i) for i in df.index]

# Create new columns
df['sum'] = [i[0] for i in result]
df['mean'] = [i[1] for i in result]

【讨论】:

    【解决方案2】:
    df = pd.read_csv(path, header = None, names=['ts','td','sa','da','sp','dp','pr','flg','fwd','stos','pkt','byt','lbl'])
            
    df['ts'] = pd.to_datetime(df['ts'])
       
    def prev_30_ip_sum(df, i):
      #current time from current row
      current = df.loc[i, 'ts']
      # timestamp of last 30 minutes 
      last = current - timedelta(minutes=30)
    
      # Current source address
      sa = df.loc[i, 'sa']
    
      # new dataframe for timestamp less than 30 min and same ip as current one
      new_df = df[(last <= df['ts']) & (current > df['ts']) & (df['sa'] == sa)]
    
      # Return sum and mean
      return new_df['pkt'].sum(), new_df['pkt'].mean()
    
    
    # Take sa and timestamp of each row and create new dataframe
    result = [prev_30_ip_sum(df, i) for i in df.index]
    
    # Create new columns in current database.
    df['sum'] = [i[0] for i in result]
    df['mean'] = [i[1] for i in result]
    

    refer this to understand timedelta

    【讨论】:

    • 我收到以下错误。 : current = df.loc(i, 'ts') TypeError: __call__() 需要 1 到 2 个位置参数,但给出了 3 个
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-26
    • 2019-02-17
    • 2022-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-09
    相关资源
    最近更新 更多