簡體   English   中英

為每一行計算在最高X%內觀察到多少列

[英]Calculate for each row for how many columns is observation within top X%

我有一個熊貓數據幀。 對於每一行,我想了解變量如何出現outlier值。 為簡單起見,我們假設將異常定義為觀察值在每列中記錄的值的頂部(底部)的5%。

換句話說,我想找出:

  1. 對於每列,找出記錄值的最高5%(如果觀察值在給定列的前5%中,則返回1,否則返回0)
  2. 行和
  3. 將標識number of outliers per row的列添加到原始數據集中

如何在python中以速度和內存高效的方式做到這一點?

使用R的示例:

讓我們有類似的數據集:

   ID v1 v2 v3
1:  a  1  2  0
2:  b  2  3  0
3:  c  1  6  1
4:  d  3  1  2
5:  e  4  0  3
6:  f  5  2  5

# set up a reproducible example
library(data.table)
df = data.table(ID = c('a', 'b', 'c', 'd', 'e', 'f'),
                v1 = c(1,2,1,3,4,5),
                v2 = c(2,3,6,1,0,2),
                v3 = c(0,0,1,2,3,5))

# function to find out the outliers
outlier_detector = function(x, type = 'positive',tail = 0.05)
{
  if (type == 'positive')
  {
    x >= quantile(x,  1 - tail)
  }
  else if (type == 'negative')
  {
    x <= quantile(x, tail)
  }
}

# add two columns to the original dataset
# sum_out_positive - for each row calculates the number of columns where within top 5%
# sum_out_negative - for each row calculates the number of columns where within bottom 5%
df[,`:=`(
  sum_out_positive = df[,2:4][
    ,
    lapply(.SD, outlier_detector)][
      ,
      rowSums(.SD, na.rm = T),
      .SDcols = paste0('v', 1:3)],
  sum_out_negative = df[, 2:4][
    ,
    lapply(.SD, outlier_detector, 'negative')][
      ,
      rowSums(.SD, na.rm = T),
      .SDcols = paste0('v', 1:3)])]

預期產量:

   ID v1 v2 v3 sum_out_positive sum_out_negative
1:  a  1  2  0                0                2
2:  b  2  3  0                0                1
3:  c  1  6  1                1                1
4:  d  3  1  2                0                0
5:  e  4  0  3                0                1
6:  f  5  2  5                2                0

在python中實現此目標的有效方法是什么? 我知道我可以編寫一個循環以遍歷所有列,並根據觀察值是否為離群值對每個觀察值返回True / False,然后執行按行求和(使用df.sum(axis = 1))。

但是我可以在不創建與原始數據幀大小相同的另一個數據幀然后在第二步執行求和的情況下執行此操作嗎? 即我想優化速度以及執行計算所需的內存量。

額外的問題:如何改善我在R中的計算?

編輯:我想我可以在python熊貓中做類似的事情:

(df.iloc[:, 1:3] >= df.iloc[:,1:3].quantile(0.95, axis = 0)).sum(axis = 1)

但這是最好的方法嗎?

這是一個解決方案,可能不是最優雅的方法,也不是最優化的方法,但是它可以工作。 希望能幫助到你:

# For each value column, indicate the outliers
for col in df.columns[1:]:
    df[f'{col}_outliers_pos'] = np.where(df[col] >= df[col].quantile(0.95), 1, 0)
    df[f'{col}_outliers_neg'] = np.where(df[col] <= df[col].quantile(0.05), 1, 0)

# Create lists for positive and negative columns 
pos_cols = [col for col in df.columns if 'pos' in col]
neg_cols = [col for col in df.columns if 'neg' in col]

# Calculate the sum of both negative and positive
df['sum_out_positive'] = df[pos_cols].sum(axis=1)
df['sum_out_negative'] = df[neg_cols].sum(axis=1)

# Drop columns we dont need to get correct output
df.drop(pos_cols + neg_cols, axis=1, inplace=True)

print(df)
  ID  v1  v2  v3  sum_out_positive  sum_out_negative
0  a   1   2   0                 0                 2
1  b   2   3   0                 0                 1
2  c   1   6   1                 1                 1
3  d   3   1   2                 0                 0
4  e   4   0   3                 0                 1
5  f   5   2   5                 2                 0

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM