#python #pandas #dataframe #numpy #data-analysis
Вопрос:
фрейм данных(ввод)
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
Ответ №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.головка():
0
0 1
1 2
2 3
3 4
4 5
res = df1[0].apply(lambda x: sum((df[1]<=x) amp; (df[2]>=x)))
RES:
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
Комментарии:
1. большое спасибо. это решило мою проблему. Я действительно ценю это, но у меня есть вопрос. можем ли мы использовать (индекс 1) вместо создания нового столбца?
2. @Хамед, Да, ты можешь это сделать.
Ответ №2:
Вы можете формировать диапазоны для каждой строки, а затем разносить их. Подсчет значений дает конечный результат:
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
: s можно заменить на range
, если значения в кадре являются целыми числами и, следовательно df = df.astype(int)
, не теряют никакой информации. Если нет, np.arange
то это необходимо. Кроме того, np.arange
инкапсулирует range
, чтобы его можно было использовать в любом случае.
Ответ №3:
Сначала нам нужно знать, сколько интервалов открывается и закрывается при каждом значении:
>>> 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
Комментарии:
1. это действительно хороший способ, за исключением того, что я хочу, чтобы 97 было 1, а не 0.
2. Ах, тогда вам просто нужно добавить сдвиг() @Hamed, я отредактирую свой ответ
3. и последний вопрос. чтобы получить хорошее представление о том, что вы делаете(у меня есть приблизительное представление о том, что вы делаете с совокупной суммой, но не совсем точное и полное понимание), какой ресурс вы рекомендуете, поскольку вы являетесь экспертом. Я действительно благодарен вам за помощь.
Ответ №4:
пробовать:
df1 = df.groupby(['ColumnName']).count()
Это вернет столбец, который вы выбрали в качестве индекса, и получит количество совпадающих интервалов
Ответ №5:
Вы можете сделать следующее. Сначала создайте новый фрейм данных со столбцом от 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
И при необходимости приведите к целочисленному
Комментарии:
1.
NaN
вместо подсчетов есть s; это не ожидаемый результат, не так ли?