gpt4 book ai didi

python - Pandas 选择具有特定列中前 2 个值之一的所有行

转载 作者:太空宇宙 更新时间:2023-11-03 13:10:02 25 4
gpt4 key购买 nike

我有以下示例数据:

IND ID  value  EFFECTIVE DT    SYSDATE
8 A 19289 6/30/2017 8/16/2017 10:05
17 A 19289 6/30/2017 8/15/2017 14:25
26 A 19289 6/30/2017 8/14/2017 15:10
7 A 18155 3/31/2017 8/16/2017 10:05
16 A 18155 3/31/2017 8/15/2017 14:25
25 A 18155 3/31/2017 8/14/2017 15:10
6 A 21770 12/31/2016 8/16/2017 10:05
15 A 21770 12/31/2016 8/15/2017 14:25
24 A 21770 12/31/2016 8/14/2017 15:10
5 A 19226 9/30/2016 8/16/2017 10:05
14 A 19226 9/30/2016 8/15/2017 14:25
23 A 19226 9/30/2016 8/14/2017 15:10
4 A 20238 6/30/2016 8/16/2017 10:05
13 A 20238 6/30/2016 8/15/2017 14:25
22 A 20238 6/30/2016 8/14/2017 15:10
3 A 18684 3/31/2016 8/16/2017 10:05
12 A 18684 3/31/2016 8/15/2017 14:25
21 A 18684 3/31/2016 8/14/2017 15:10
2 A 22059 12/31/2015 8/16/2017 10:05
11 A 22059 12/31/2015 8/15/2017 14:25
20 A 22059 12/31/2015 8/14/2017 15:10
1 A 19280 9/30/2015 8/16/2017 10:05
10 A 19280 9/30/2015 8/15/2017 14:25
19 A 19280 9/30/2015 8/14/2017 15:10
0 A 20813 6/30/2015 8/16/2017 10:05
9 A 20813 6/30/2015 8/15/2017 14:25
18 A 20813 6/30/2015 8/14/2017 15:10

是我每个工作日收集的一组数据(SYSDATE是时间戳)。

我想生成一个 df,其中仅包含每天标记有两个最新时间戳值之一的行。

所以如果我今天要运行脚本,我希望得到这个(来自具有许多时间戳的更大的集合):

IND ID  Value   EFFECTIVE DT    SYSDATE
8 A 19289 6/30/2017 8/16/2017 10:05
17 A 19289 6/30/2017 8/15/2017 14:25
7 A 18155 3/31/2017 8/16/2017 10:05
16 A 18155 3/31/2017 8/15/2017 14:25
6 A 21770 12/31/2016 8/16/2017 10:05
15 A 21770 12/31/2016 8/15/2017 14:25
5 A 19226 9/30/2016 8/16/2017 10:05
14 A 19226 9/30/2016 8/15/2017 14:25
4 A 20238 6/30/2016 8/16/2017 10:05
13 A 20238 6/30/2016 8/15/2017 14:25
3 A 18684 3/31/2016 8/16/2017 10:05
12 A 18684 3/31/2016 8/15/2017 14:25
2 A 22059 12/31/2015 8/16/2017 10:05
11 A 22059 12/31/2015 8/15/2017 14:25
1 A 19280 9/30/2015 8/16/2017 10:05
10 A 19280 9/30/2015 8/15/2017 14:25
0 A 20813 6/30/2015 8/16/2017 10:05
9 A 20813 6/30/2015 8/15/2017 14:25

由于周末和节假日,我无法使用日期时间。

建议?

提前致谢。

最佳答案

您首先需要确保将SYSDATE 转换为datetime。我也会为 EFFECTIVE DT 做这件事。

df[['EFFECTIVE DT', 'SYSDATE']] = \
df[['EFFECTIVE DT', 'SYSDATE']].apply(pd.to_datetime)

选项 1
pir1
groupby.apply 与数据框方法一起使用 pd.DataFrame.nlargest为最大的两个 'SYSDATE' 传递参数 columns='SYSDATE'n=2

df.groupby(
'EFFECTIVE DT', group_keys=False, sort=False
).apply(pd.DataFrame.nlargest, n=2, columns='SYSDATE')

IND ID value EFFECTIVE DT SYSDATE
0 8 A 19289 2017-06-30 2017-08-16 10:05:00
1 17 A 19289 2017-06-30 2017-08-15 14:25:00
3 7 A 18155 2017-03-31 2017-08-16 10:05:00
4 16 A 18155 2017-03-31 2017-08-15 14:25:00
6 6 A 21770 2016-12-31 2017-08-16 10:05:00
7 15 A 21770 2016-12-31 2017-08-15 14:25:00
9 5 A 19226 2016-09-30 2017-08-16 10:05:00
10 14 A 19226 2016-09-30 2017-08-15 14:25:00
12 4 A 20238 2016-06-30 2017-08-16 10:05:00
13 13 A 20238 2016-06-30 2017-08-15 14:25:00
15 3 A 18684 2016-03-31 2017-08-16 10:05:00
16 12 A 18684 2016-03-31 2017-08-15 14:25:00
18 2 A 22059 2015-12-31 2017-08-16 10:05:00
19 11 A 22059 2015-12-31 2017-08-15 14:25:00
21 1 A 19280 2015-09-30 2017-08-16 10:05:00
22 10 A 19280 2015-09-30 2017-08-15 14:25:00
24 0 A 20813 2015-06-30 2017-08-16 10:05:00
25 9 A 20813 2015-06-30 2017-08-15 14:25:00

工作原理
pandas 的一个关键特性是开始、拆分、将东西应用到拆分以及重新组合你的努力,这里有很好的解释 split-apply-combine .

groupby 元素应该是不言自明的。我想按照 'EFFECTIVE DT' 列中的日期定义的每一天对数据进行分组。之后,您可以使用此 groupby 对象做很多事情。我决定应用一个函数,该函数将返回对应于 'SYSDATE' 列的两个最大值的 2 行。这些最大值等于该组当天的最新值。

事实证明,有一种数据框方法可以执行此任务,即返回与列的最大值相对应的行。即,pd.DataFrame.nlargest

需要注意两点:

  1. 当我们使用 groupby.apply 时,传递给正在应用的函数的对象是一个 pd.DataFrame 对象。
  2. 当使用像 pd.DataFrame.nlargest 这样的方法作为函数时,预期的第一个参数是 pd.DataFrame 对象。

好吧,这很幸运,因为这正是我正在做的事情。

此外,groupby.apply 允许您通过 kwargs 将额外的关键字参数传递给应用函数。因此,我可以轻松传递 n=2columns='SYSDATE'


选项 2
pir2
与选项 1 相同的概念,但使用 np.argpartion

def nlrg(d):
v = d.HOURS.values
a = np.argpartition(v, v.size - 2)[-2:]
return d.iloc[a]

pir2 = lambda d: d.groupby('DAYS', sort=False, group_keys=False).apply(nlrg)

选项 3
pir4
使用 numba.njit
我扫描跟踪最后两个最大值的列表。

form numba import njit

@njit
def nlrg_nb(f, v, i, n):
b = (np.arange(n * 2) * 0).reshape(-1, 2)
e = b * np.nan
for x, y, z in zip(f, v, i):
if np.isnan(e[x, 0]):
e[x, 0] = y
b[x, 0] = z
elif y > e[x, 0]:
e[x, :] = [y, e[x, 0]]
b[x, :] = [z, b[x, 0]]
elif np.isnan(e[x, 1]):
e[x, 1] = y
b[x, 1] = z
elif y > e[x, 1]:
e[x, 1] = y
b[x, 1] = z
return b.ravel()[~np.isnan(e.ravel())]

def pir4(d):
f, u = pd.factorize(d.DAYS.values)
return d.iloc[nlrg_nb(f, d.HOURS.values.astype(float), np.arange(f.size), u.size)]

时间

结果

(lambda r: r.div(r.min(1), 0))(results)

pir1 pir2 pir4 jez1
100 24.205348 9.725718 1.0 4.449165
300 42.685989 15.754161 1.0 4.047182
1000 111.733703 39.822652 1.0 4.175235
3000 253.873888 74.280675 1.0 4.105493
10000 376.157526 125.323946 1.0 4.313063
30000 434.815009 145.513904 1.0 5.296250

enter image description here

模拟

def produce_test_df(i):
hours = pd.date_range('2000-01-01', periods=i, freq='H')[np.random.permutation(np.arange(i))]
days = hours.floor('D')
return pd.DataFrame(dict(HOURS=hours, DAYS=days))

results = pd.DataFrame(
index=[100, 300, 1000, 3000, 10000, 30000],
columns='pir1 pir2 pir4 jez1'.split(),
dtype=float,
)

for i in results.index:
d = produce_test_df(i)
for j in results.columns:
stmt = '{}(d)'.format(j)
setp = 'from __main__ import d, {}'.format(j)
results.set_value(i, j, timeit(stmt, setp, number=20))

results.plot(loglog=True)

函数

def nlrg(d):
v = d.HOURS.values
a = np.argpartition(v, v.size - 2)[-2:]
return d.iloc[a]

pir1 = lambda d: d.groupby('DAYS', group_keys=False, sort=False).apply(pd.DataFrame.nlargest, n=2, columns='HOURS')
pir2 = lambda d: d.groupby('DAYS', sort=False, group_keys=False).apply(nlrg)
jez1 = lambda d: d.sort_values(['DAYS', 'HOURS']).groupby('DAYS').tail(2)

@njit
def nlrg_nb(f, v, i, n):
b = (np.arange(n * 2) * 0).reshape(-1, 2)
e = b * np.nan
for x, y, z in zip(f, v, i):
if np.isnan(e[x, 0]):
e[x, 0] = y
b[x, 0] = z
elif y > e[x, 0]:
e[x, :] = [y, e[x, 0]]
b[x, :] = [z, b[x, 0]]
elif np.isnan(e[x, 1]):
e[x, 1] = y
b[x, 1] = z
elif y > e[x, 1]:
e[x, 1] = y
b[x, 1] = z
return b.ravel()[~np.isnan(e.ravel())]

def pir4(d):
f, u = pd.factorize(d.DAYS.values)
return d.iloc[nlrg_nb(f, d.HOURS.values.astype(float), np.arange(f.size), u.size)]

关于python - Pandas 选择具有特定列中前 2 个值之一的所有行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45721669/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com