熊猫:检查一个数字是否连续出现多次

时间:2018-01-23 00:55:46

标签: python pandas

假设我有一个如下数据框。我想要的是,如果列a,b,c之间的数字出现最多,那么它应输出该数字,或者如果所有三个数字不同,则取a的数字。例如,在第一行中,1出现在1和5中最多,然后d中的输出为1.但在第二行中,列a,b,c的所有三个数字11,2,7都不同,输出是列的值a(11),所以d中的输出是11

list   a  b   c  
 1     1  5   1 
11    11  2   7 
 0     0  0   0 
 9     5  9   5 
 8     8  2   7  

预期输出

list   a  b   c  d 
 1     1  5   1  1
11    11  2   7  11
 0     0  0   0  0
 9     5  9   5  5
 8     8  2   7  8 

4 个答案:

答案 0 :(得分:1)

scipy计算模式,但我很惊讶,不要在numpy中找到它。

import pandas as pd
import numpy as np
from scipy import stats

df = pd.DataFrame([[1, 1, 5, 1],
                   [11, 11, 2, 7],
                   [0, 0, 0, 0],
                   [9, 5, 9, 5],
                   [8, 8, 2, 7]],
                  columns=['list', 'a', 'b', 'c'])

df['d'], df['count'] = stats.mode(df[['a', 'b', 'c']].values, axis=1)
df.loc[df['count'] == 1, 'd'] = df['a']
df = df.drop('count', 1)

答案 1 :(得分:1)

您可以使用value_counts

df.iloc[:,1:].apply(lambda x : x.value_counts().index[0] if x.value_counts().iloc[0]>1 else x['a'] ,1)
Out[1046]: 
0     1
1    11
2     0
3     5
4     8
dtype: int64

答案 2 :(得分:1)

这是我的bincount解决方案

数据
请注意,这与OP的不同之处在于指出它按预期工作。

   list   a  b  c
0     1   5  1  1
1    11  11  2  7
2     0   0  0  0
3     9   5  9  5
4     8   8  2  7

解决方案

v = df.values[:, 1:]

f, u = pd.factorize([(i, e) for i, row in enumerate(v) for e in row])

counts = np.bincount(f)[f].reshape(v.shape)

x = (counts == counts.max(1, keepdims=1)).argmax(1)
y = np.arange(v.shape[0])

df.assign(d=v[y, x])

   list   a  b  c   d
0     1   5  1  1   1
1    11  11  2  7  11
2     0   0  0  0   0
3     9   5  9  5   5
4     8   8  2  7   8

详情

获取我们想要的值的numpy数组。

v = df.values[:, 1:]

使用enumerate和理解来创建元组列表。每个行值将与其他行不同,因为我在每个行的元组的第一个位置放置一个标识符。即枚举值。然后我将这些传递给Pandas的factorize函数,以便放入Numpy的bincount

f, u = pd.factorize([(i, e) for i, row in enumerate(v) for e in row])

现在我在bincount上使用f并使用f对其进行切片以获得相同大小的数组,但现在已填充计数值。

counts = np.bincount(f)[f].reshape(v.shape)

我找到了最大值并对原始数组进行切片以获得那些值所在的位置。

x = (counts == counts.max(1, keepdims=1)).argmax(1)
y = np.arange(v.shape[0])

请注意,如果所有值都相同或者有多种模式,argmax将选择第一个。如果全部相同,则为a列。

df.assign(d=v[y, x])

答案 3 :(得分:0)

正如@piRSquared建议的那样,我们可以在pandas中使用mode函数。

df["d"] = np.where(df.apply(lambda x: x.nunique() == 3, 1), 
                   df["a"], 
                   df.mode(1).loc[:,0])

另一种方法(为了好玩)

df["d"] = np.where(df['b'] == df['c'], df['b'], df['a']) 

伪代码解释

if b == c:
    choose b because b and c are both the mode
else:  # when b != c
   if a == c or a == b:
        choose a because a is the mode
   else: # a != b != c
        choose a because all are different