如何使用熊猫过滤值?

时间:2020-06-26 13:50:18

标签: python pandas numpy

意图:使用熊猫根据汉明权重过滤二进制数。在这里,我检查二进制文件中出现的1的数目,并将计数写入df。

到目前为止的努力:

import pandas as pd
def ones(num):
    return bin(num).count('1')
num = list(range(1,8))
C = pd.Index(["num"])
df = pd.DataFrame(num, columns=C)
df['count'] = df.apply(lambda row : ones(row['num']), axis = 1)
print(df) 

输出:

   num  count
0    1      1
1    2      1
2    3      2
3    4      1
4    5      2
5    6      2
6    7      3


Intended output:
  1 2 3
0 1 3 7
1 2 5
2 4 6

帮助!

3 个答案:

答案 0 :(得分:3)

您可以使用pivot_table。尽管您需要将index定义为分组的cumcount列的count,但是pivot_table不能自己解决所有问题:)

(df.pivot_table(index=df.groupby('count').cumcount(), 
                columns='count', 
                values='num'))

count    1    2    3
0      1.0  3.0  7.0
1      2.0  5.0  NaN
2      4.0  6.0  NaN

您也有参数fill_value,尽管我不建议您使用它,因为您会得到混合类型。现在看来NumPy是一个不错的选择,您可以使用new_df.to_numpy()轻松地从结果中获取一个数组。


此外,我们着眼于ones中的逻辑,我们可以将其向量化(基于this answer):

m = df.num.to_numpy().itemsize
df['count'] = (df.num.to_numpy()[:,None] & (1 << np.arange(m)) > 0).view('i1').sum(1)

这是对两种方法性能的检验:

df_large = pd.DataFrame({'num':np.random.randint(0,10,(10_000))})

def vect(df):
    m = df.num.to_numpy().itemsize
    (df.num.to_numpy()[:,None] & (1 << np.arange(m)) > 0).view('i1').sum(1)

%timeit vect(df_large)
# 340 µs ± 5.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit df_large.apply(lambda row : ones(row['num']), axis = 1)
# 103 ms ± 2.32 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

答案 1 :(得分:1)

我建议使用其他输出:

var1 + var2

这会给你

num = input()
n = int(num)

if n%2 !=0:
    print('Weird')
if n%2==0 and n in range(2,6):
    print('Not Weird')
if n%2==0 and n in range(6,21):
    print('Weird')
if n%2==0 and n>20:
    print('Not Weird')
else:
    pass

是相同的信息,但格式略有不同。在原始的透视格式下,行是没有意义的,并且列的数量不确定。我建议行数不确定的情况更为常见。我认为您会发现此操作更容易进行。

或者考虑仅创建字典,因为DataFrame在这里增加了很多开销,但毫无益处:

df.groupby("count").agg(list)

给你

             num
count           
1      [1, 2, 4]
2      [3, 5, 6]
3            [7]

答案 2 :(得分:0)

这是一种方法

df.groupby('count')['num'].agg(list).apply(pd.Series).T