簡體   English   中英

為數據框中的每一行查找n個最低值

[英]Finding n lowest values for each row in a dataframe

我有一個包含1739行和1455列的大型數據幀。 我想找到每行150個最低值(不是第150個值,而是150個值)。

我用一個基本的for循環遍歷行。

我嘗試了df.min(axis=1)但它只給出了一分鍾。 而且rolling_min函數也沒有成功。

是否有任何現有功能,我可以輸入我想找到的值的數量.min?

我的最終目標是取150個最低值並創建斜率然后計算曲線下面積。 對每行執行此操作並添加區域以獲取卷。

數據幀的示例,我有一個看起來像這樣的df:

     -218.7     -218.4    ...          217.2      217.5
0     56.632706  13.638315    ...      76.543000  76.543000
1     56.633455  13.576762    ...      76.543000  76.543000
2    -18.432203 -18.384091    ...      76.543000  76.543000
3    -18.476594 -18.439804    ...      76.543000  76.543000

標題是'-218.7 ...',它是掃描的x軸中的坐標。 數據是y軸掃描的高度。 我需要的是每行150個最低值以及相關的列標題,因為我想為每一行制作一條曲線然后計算曲線下面積。

所以我需要為每一行這樣的東西:

         -218.7     -218.4    ... for 150 columns
4    -18.532035 -18.497517    ... for 150 values

我不認為我需要存儲每行的標題信息,for循環將逐個通過每一行。

使用.argsort來獲取基礎數組的索引。 切片值和列索引以獲取所需的所有信息。 我們將創建一個MultiIndex,以便我們可以將列標題和值存儲在同一個DataFrame中。 第一級將是您的原始索引。

例:

import pandas as pd
import numpy as np

np.random.seed(1)
df = pd.DataFrame(np.random.randint(1,100000, (1739, 26)))
df.columns = list('ABCDEFGHIJKLMNOPQRSTUVWXYZ')

N = 7  # 150 in your case
idx = np.argsort(df.values, 1)[:, 0:N]

pd.concat([pd.DataFrame(df.values.take(idx), index=df.index),
           pd.DataFrame(df.columns[idx], index=df.index)],
           keys=['Value', 'Columns']).sort_index(level=1)

輸出:

                 0      1      2      3      4      5      6
Columns 0        C      K      U      V      I      G      P
Value   0     5193   7752   8445  19947  20610  21441  21759
Columns 1        R      J      W      C      B      D      G
Value   1      432   3607  16278  17138  19434  26104  33879
Columns 2        K      S      E      F      M      O      U
Value   2       16   1047   1845   9553  12314  13784  19432
Columns 3        K      Q      A      S      X      W      G
Value   3      244   5272  10836  13682  29237  33230  34448
Columns 4        K      T      L      U      C      D      M
Value   4     9765  11275  13160  22808  30870  33484  42760
...
Columns 1736     I      L      U      W      B      X      N
Value   1736  7099   7922  11047  12613  15502  18409  21576
Columns 1737     J      K      E      V      O      M      S
Value   1737  3000   5538   7933  13777  17310  22640  24750
Columns 1738     O      U      A      X      E      I      F
Value   1738  5118   5775  10267  11320  17659  30055  30702

如果我理解正確,問題歸結為在M(> k)數字列表中獲得k個最小數字。 然后將其單獨應用於每一行。

如果numpy可用且順序無關緊要,你可以嘗試使用argpartition :給定參數k,它以假定第k個元素被放入其排序位置的方式對數組進行分區,所有較小的數字都在之前,所有較大的數字都在后面(以未指定的順序):

import numpy as np
row = np.array([1, 6, 2, 12, 7, 8, 9, 11, 15, 26])
k = 5
idx = np.argpartition(row, k)[:k]

print(idx)
print(row[idx])

-->
[1 0 2 4 5]
[6 1 2 7 8]

編輯 :這也適用於完整數組的行/明智:

import numpy as np
data = np.array([
    [1, 6, 2, 12, 7, 8, 9, 11, 15, 26],
    [1, 65, 2, 12, 7, 8, 9, 11, 15, 26],
    [16, 6, 2, 12, 7, 8, 9, 11, 15, 26]])
k = 5
idx = np.argpartition(data, k)[:,:k]

print(idx)

-->
[[1 0 2 4 5]
 [2 0 4 5 6]
 [4 2 1 5 6]]

您可以使用heapq.nsmallest查找列表中的n最小數字。 這可以使用.apply快速應用於數據幀的每一行:

import pandas as pd
import numpy as np
import heapq

df = pd.DataFrame(np.random.randn(1000, 1000))

# Find the 150 smallest values in each row
smallest = df.apply(lambda x: heapq.nsmallest(150, x), axis=1)

每行最小值現在是df相應行中150個最小值的列表。

可以使用以下方法將其轉換為數據框:

smallest_df = pd.DataFrame(smallest.values.tolist())

現在這是一個數據框,其中每一行對應於原始數據框中的每一行。 有150列,原始的每一行中有150個最小值。

smallest_df.head()

smallest_df

我不知道如何在不循環遍歷行的情況下執行此操作:

df = df.transpose()
for col in df.columns:
    min_values = df[col].sort_values()[0:150]
    # now calc slope/area

如果你使用for循環迭代df,就像你在問題中提到的那樣,你可以簡單地這樣做:

for index, row in df.iterrows(): # your loop
    new_row = sorted(row.values)[:150]
    # new_row should be a list with length 150.

測試:

import numpy
import pandas
import random

# generate dummy data
l = list(range(1600))
random.shuffle(l)
a = numpy.array(l)
a = a.reshape(40, 40) # columns x rows
dummy_df = pandas.DataFrame(a)

# dummy_df.shape = (40, 40)

smallest = []
for idx, row in dummy_df.iterrows():
    smallest.append(sorted(row.values)[:10])

new_df = pandas.DataFrame(numpy.array(smallest))
# new_df.shape = (40, 10)

暫無
暫無

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

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