我有以下数据框:

Name1  Number1  Name2  Number2  Group
 R       1        G       5       1
 B       EXP      Y       9       2
 Y       225      L       185     2
 F       17       D       2       2
 H       259      G       175     3
 X       172      Q       EXP     3

我试着在每个“组”中搜索,看看每个数字列中的任何数字是否在某个范围内。如果在该范围内存在组中的一个值,则我希望将组中的所有名称追加到列表中。一个很大的障碍是数字列可以包含偶尔出现的字符串,这些字符串的处理方式与超出范围的数字相同。
在这个例子中,我们会说范围是200-300
搜索组后得到的列表将是:
L = [B,Y,Y,L,F,D,H,G,X,Q]

请注意,列表中未包含组1中的名称,因为组1在指定范围内的Number1/Number2列中不包含任何值。
我的代码:
newList = {}
dict_of_groups = {k: v for k, v in df.groupby('Group')}
for df in dict_of_groups.values()
    if df[df['Number1'] | df['Number2'] > 199]: #how do I specify AND < 300 here?
        a = df['Number1'].values.tolist()
        b = df['Number2'].values.tolist()
        newList.update(a,b)

我对如何有效地操作dict-of-dataframes中的每个数据帧有点困惑。关于如何最好地与这些团队合作有什么建议吗?

最佳答案

列中有一些无效值,必须将这些值转换为有效的数值才能执行有效的比较。这里有两个选项,您可以只使用pandas操作,执行较慢的groupby,也可以下拉到numpy以获得非常有效的解决方案。
选择1
stack+unstack+groupby+transform+numpy

names = df.filter(like='Name').to_numpy()

m = (pd.to_numeric(df.filter(like='Number').stack(), errors='coerce')
      .between(200, 300).unstack())

mask = m.groupby(df['Group']).transform('any').any(1)

names[mask].ravel().tolist()

['B', 'Y', 'Y', 'L', 'F', 'D', 'H', 'G', 'X', 'Q']

选择2
使用np.add.at和一些掩蔽的快速解决方案
a = df.filter(like='Name').to_numpy().ravel()
b = df.filter(like='Number').to_numpy().ravel()
c = np.repeat(df['Group'].to_numpy(), a.shape[0] // df.shape[0])
n = pd.to_numeric(b, errors='coerce')


f = np.zeros(c.max()+1, dtype=int)
m = np.logical_and(n >= 200, n <= 300)
np.add.at(f, c, m)

mask = f[c].astype(bool)

a[mask]

array(['B', 'Y', 'Y', 'L', 'F', 'D', 'H', 'G', 'X', 'Q'], dtype=object)

时间安排
df = pd.concat([df]*1000, ignore_index=True)

%timeit chris_stack()
22.7 ms ± 1.86 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

%timeit chris_numpy()
11.9 ms ± 153 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\

%timeit quang()
16.7 ms ± 101 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit jezrael()
78.5 ms ± 685 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

关于python - 操作数据框字典,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57806220/

10-11 14:32
查看更多