我有一个 DataFrame ,其中包含某些间隔的第一个和最后一个数字。我怎样才能得到每个数字在每个间隔中出现了多少次?

I have a DataFrame which contains first and last number of some intervals. how can I get how many times each number was in each interval?

DataFrame(输入)

0     1.0     25.0
1     1.0     31.0
2     2.0     97.0
3     1.0     25.0
4     1.0     26.0

输出

我想得到一个索引从 1 到 97 的数组,它表示每个索引是间隔的次数,例如 1 在 4 个间隔(前两个和后两个间隔)中,3 在5个区间,96只在1个区间。请注意,我不能使用循环,我必须使用数组操作(numpy,pandas)。

我想得到类似的东西:

1    4 
2    5
3    5
.
.
.
25   5 
26   3
27   2
28   2
29   2
30   2
31   2
32   1
33   1
34   1
.
.
. 
97   1

尝试:

df1 = pd.DataFrame(data=[i for i in range(1,98)])

df:

    0   1       2
0   0   1.0     25.0
1   1   1.0     31.0
2   2   2.0     97.0
3   3   1.0     25.0
4   4   1.0     26.0

df1.head():

    0
0   1
1   2
2   3
3   4
4   5

res = df1[0].apply(lambda x: sum((df[1]<=x) & (df[2]>=x)))

结果:

0     4
1     5
2     5
3     5
4     5
     ..
92    1
93    1
94    1
95    1
96    1
Name: 0, Length: 97, dtype: int64

您可以每行形成范围,然后分解它们。计算值给出最终结果:

result = (pd.Series(np.arange(first, second+1) for first, second in df.to_numpy())
                   .explode()
                   .value_counts(sort=False))

得到

>>> result

1.0     4
2.0     5
3.0     5
4.0     5
5.0     5
       ..
93.0    1
94.0    1
95.0    1
96.0    1
97.0    1

这不一定包括 1..97 中的所有值,因为如果一个数字落在每个区间之外,它就不会被计算在内。为了保证索引为 1..97,我们可以用最小值和最大值(即这里的 1 和 97)重新索引,并将 0 放入那些没有出现的值:

values = df.to_numpy()
min_, max_ = values.min(), values.max()

result = result.reindex(np.arange(min_, max_+1), fill_value=0)

最后要注意的是,如果帧中的值是整数,则 np.arange 可以替换为 range,因此 df = df.astype(int) 不会丢失任何信息。如果不是,则需要 np.arange。此外,np.arange 封装了 range,因此它可以在任何一种情况下使用。

您可以按照以下方式进行操作。首先用 1 到 97

的列创建一个新的数据框
>>> df2 = pd.DataFrame(list(range(1,98,1)), dtype=float, columns=["range"])
>>> df2
    range
0     1.0
1     2.0
2     3.0
3     4.0
4     5.0
..    ...
92   93.0
93   94.0
94   95.0
95   96.0
96   97.0

从原始数据框中获取值的计数

>>> dfg = df.groupby('val').agg('count')
>>> dfg
     range
val
1.0      4
2.0      1

现在从您的 df 映射,同时用零填充缺失值。然后转换为整数以匹配 OP 的预期格式。

>>> df2["count"] = df2["range"].map(dfg['range']).fillna(0)
>>> df2 = df2.astype(int)
>>> df2
    range  count
0       1      4
1       2      1
2       3      0
3       4      0
4       5      0
..    ...    ...
92     93      0
93     94      0
94     95      0
95     96      0
96     97      0

如果需要,转换为整数

尝试:

df1 = df.groupby(['ColumnName']).count()

这将return您选择的列作为索引并获得匹配间隔的计数

首先我们需要知道每个值有多少个区间开盘和收盘:

>>> df
    col_1 col_2
0     1.0  25.0
1.0   1.0  31.0
2.0   2.0  97.0
3.0   1.0  25.0
4.0   1.0  26.0
>>> idx = pd.RangeIndex(1, 98)
>>> opencount = df['col_1'].value_counts().reindex(idx, fill_value=0)
>>> closecount = df['col_2'].value_counts().reindex(idx, fill_value=0)
>>> opencount
1     3
2     1
3     0
4     0
5     0
 ..
93    0
94    0
95    0
96    0
97    0
Name: col_1, Length: 97, dtype: int64
>>> closecount
1     0
2     0
3     0
4     0
5     0
 ..
93    0
94    0
95    0
96    0
97    1
Name: col_2, Length: 97, dtype: int64

请注意,我们使用 reindexcol_1col_2 中不可用的所有值处添加零。

如果实际上间隔的结尾包含在间隔中(根据评论),您只需将 closecount 向下移动 1:

>>> closecount = closecount.shift(fill_value=0)
>>> closecount
1     0
2     0
3     0
4     0
5     0
     ..
93    0
94    0
95    0
96    0
97    0
Name: col_2, Length: 97, dtype: int64

然后我们可以计算每个点的区间数,即之前打开的区间之和减去之前关闭的区间之和。这可以通过 cumsum

来完成
>>> opencount.cumsum() - closecount.cumsum()
1     4
2     5
3     5
4     5
5     5
     ..
93    1
94    1
95    1
96    1
97    1
Length: 97, dtype: int64