我有一个非常简单的问题-我想-但似乎我无法解决这个问题。我是Python和Pandas的初学者。我在论坛上进行了搜索,但没有得到符合我需要的(最新)答案。
我有一个这样的数据框:
df = pd.DataFrame({'A': [1.1, 2.7, 5.3], 'B': [2, 10, 9], 'C': [3.3, 5.4, 1.5], 'D': [4, 7, 15]}, index = ['a1', 'a2', 'a3'])
这使:
A B C D
a1 1.1 2 3.3 4
a2 2.7 10 5.4 7
a3 5.3 9 1.5 15
我的问题很简单:我想添加一列,以给出 每一行 第二个 最大值的列名。
我编写了一个简单的函数,该函数返回每一行的第二个最大值
def get_second_best(x):
return sorted(x)[-2]
df['value'] = df.apply(lambda row: get_second_best(row), axis=1)
这使:
A B C D value
a1 1.1 2 3.3 4 3.3
a2 2.7 10 5.4 7 7.0
a3 5.3 9 1.5 15 9.0
但是我找不到如何在“值”列中显示列名,而不是值…我正在考虑布尔索引(将“值”列的值与每一行进行比较),但是我还没有t想出了怎么做。
更清楚地说,我希望它是:
A B C D value
a1 1.1 2 3.3 4 C
a2 2.7 10 5.4 7 D
a3 5.3 9 1.5 15 B
任何帮助(和解释)表示赞赏!
一种方法是使用来选择每一行中的两个最大元素,Series.nlargest
并使用来找到对应于最小元素的列Series.idxmin
:
In [45]: df['value'] = df.T.apply(lambda x: x.nlargest(2).idxmin())
In [46]: df
Out[46]:
A B C D value
a1 1.1 2 3.3 4 C
a2 2.7 10 5.4 7 D
a3 5.3 9 1.5 15 B
值得注意的是捡Series.idxmin
了DataFrame.idxmin
可以有所作为的性能代价:
df = pd.DataFrame(np.random.normal(size=(100, 4)), columns=['A', 'B', 'C', 'D'])
%timeit df.T.apply(lambda x: x.nlargest(2).idxmin()) # 39.8 ms ± 2.66 ms
%timeit df.T.apply(lambda x: x.nlargest(2)).idxmin() # 53.6 ms ± 362 µs
编辑:添加到@jpp的答案,如果性能很重要,则可以通过使用Numba,像编写C一样编写代码并将其编译来大大提高速度:
from numba import njit, prange
@njit
def arg_second_largest(arr):
args = np.empty(len(arr), dtype=np.int_)
for k in range(len(arr)):
a = arr[k]
second = np.NINF
arg_second = 0
first = np.NINF
arg_first = 0
for i in range(len(a)):
x = a[i]
if x >= first:
second = first
first = x
arg_second = arg_first
arg_first = i
elif x >= second:
second = x
arg_second = i
args[k] = arg_second
return args
让我们比较形状分别为(1000, 4)
和的两组数据的不同解决方案(1000, 1000)
:
df = pd.DataFrame(np.random.normal(size=(1000, 4)))
%timeit df.T.apply(lambda x: x.nlargest(2).idxmin()) # 429 ms ± 5.1 ms
%timeit df.columns[df.values.argsort(1)[:, -2]] # 94.7 µs ± 2.15 µs
%timeit df.columns[np.argpartition(df.values, -2)[:,-2]] # 101 µs ± 1.07 µs
%timeit df.columns[arg_second_largest(df.values)] # 74.1 µs ± 775 ns
df = pd.DataFrame(np.random.normal(size=(1000, 1000)))
%timeit df.T.apply(lambda x: x.nlargest(2).idxmin()) # 1.8 s ± 49.7 ms
%timeit df.columns[df.values.argsort(1)[:, -2]] # 52.1 ms ± 1.44 ms
%timeit df.columns[np.argpartition(df.values, -2)[:,-2]] # 14.6 ms ± 145 µs
%timeit df.columns[arg_second_largest(df.values)] # 1.11 ms ± 22.6 µs
在最后一种情况下,通过使用@njit(parallel=True)
并替换为外环,我可以挤出更多一点并将基准降低到852 µs for k in prange(len(arr))
。
问题内容: 已关闭 。这个问题需要更加集中。它当前不接受答案。 想改善这个问题吗? 更新问题,使其仅通过编辑此帖子来关注一个问题。 7个月前关闭。 我有这样定义的员工和薪水表: 我可以使用什么查询来获得该表中第二高的薪水? 问题答案: 这是关系的原因。 编辑: 我接受了Manoj的第二篇文章,对其进行了调整,并使它更具可读性。对我来说 n-1 不直观;但是,使用我想要的值是2 = 2nd,3 =
这似乎是一个可笑的简单问题。。。但我没有看到我期待的简单答案。 那么,我如何在Pandas中获得给定列的第n行的值呢?(我对第一排特别感兴趣,但对更普遍的做法也感兴趣)。 例如,假设我想将中的1.2值作为变量。 做这件事的正确方法是什么?
问题内容: 我有这张桌子: 如何为每个名称获得年份第二高的行,如下所示: 我尝试了以下查询,但没有成功: 上一个查询给了我这个错误:“ SQL错误(1235):此版本的MySQL尚不支持’LIMIT&IN / ALL / ANY / SOME子查询’” 而且我现在无法更改MySQL版本(5.6.25),因为该解决方案已经投入生产。 有什么帮助吗? 问题答案: 在MySQL中,每个组求解n的一种方法
问题内容: 桌子: 我想获取UserId,每个UserId的max(Date)值。即,具有最新日期的每个UserId的值。有没有一种方法可以简单地在SQL中做到这一点?(最好是Oracle) 更新: 对于任何歧义,我们深表歉意:我需要获取所有UserIds。但是对于每个UserId,仅该用户具有最新日期的那一行。 问题答案: 这将检索其my_date列值等于该用户ID的my_date最大值的所有行
问题内容: 我尝试过但失败了: 问题答案: 使用 GREATEST() 例如: 注意:每当那时任何单个值包含null时,此函数始终返回null(感谢用户@ sanghavi7)
问题内容: 我有一个这样的清单: 如果仅使用该方法,它将返回答案,如果我试图找到max name ,那将是正确的,但是我试图返回其整数最大的元素。 问题答案: 之所以起作用,是因为 max 函数的 key 参数指定了一个函数,当 max 想要知道用于搜索最大元素的值时,该函数将被调用。 max 将为序列中的每个元素调用该函数。并创建一个接收列表并返回第一个(从零开始计数)元素的小函数。所以 __