我有一个 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
请注意,我们使用 reindex
在 col_1
和 col_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
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
请注意,我们使用 reindex
在 col_1
和 col_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