[英]Pythonic way to find key of weighted minimum and maximum from a dictionary
[英]How to apply panda group by with minimum and maximum size condition (Pythonic way)
我在 pandas 中有一個 dataframe ,我需要將其分組並存儲在一個新數組中,在該數組中我需要具有特定大小的每個組的大小,如果超過最小大小,則應將其添加到具有最小的尺寸。 例如,在我對數據進行分組后,我將擁有一組G
,即len(G)<=b
、 len(G)>=a
或a <= len(G) <= b
。 所以,我需要用len(G)>=a
使組滿足條件a <= len(G) <= b
。
該代碼現在正在運行。 所以,我想知道是否有更方便的方法來做到這一點。
import numpy as np
import pandas as pd
rng = np.random.default_rng() # Just for testing
df = pd.DataFrame(rng.integers(0, 10, size=(1000, 4)), columns=list('ABCD'))
# The dataframe is grouped depend on specific column.
ans = [pd.DataFrame(y) for x, y in df.groupby(df.columns[3], as_index=False)]
n = 20 # The maximum size of the group is 25
new_arrayi_index = 0
new_array = []
for count_index in range(len(ans)):
l = ans[count_index]
if len(l) > n:
df_shuffled = pd.DataFrame(l).sample(frac=1)
final = [df_shuffled[i:i+n] for i in range(0,df_shuffled.shape[0],n)]
for inde in range(len(final)):
if len(final[inde]) <= 5 and new_arrayi_index != 0: #The minimum size of the group is 5
new_array[new_arrayi_index - 1]=new_array[new_arrayi_index - 1]+final[inde]
else:
new_array.append(final[inde])
new_arrayi_index += 1
else:
new_array.append(l)
new_arrayi_index += 1
count_index_ = 0
for count_index in range(len(new_array)):
print("count", count_index, "Size", len(new_array[count_index]))
print(new_array[count_index])
count_index_ += count_index
print(count_index_)
將此行 -> ans = [pd.DataFrame(y) for x, y in df.groupby(df.columns[3], as_index=False)]
更改為ans = [pd.DataFrame(y) for x, y in df.groupby(df.columns[3].min(), as_index=False)]
for min
和ans = [pd.DataFrame(y) for x, y in df.groupby(df.columns[3].max(), as_index=False)]
for max
我寫了一個 function 將 dataframe 分成等於最大大小的塊。 它檢查最后一個塊的剩余部分的大小,如果剩余部分小於最小大小,它將最后兩個塊分成大小大致相等的兩個塊。
在拆分大型 pandas dataframe時建立答案
import numpy as np
import pandas as pd
rng = np.random.default_rng(seed=1) # Just for testing
df = pd.DataFrame(rng.integers(0, 10, size=(1000, 4)), columns=list('ABCD'))
# The dataframe is grouped depend on specific column.
n = 20 # The maximum size of the group is 25
# https://stackoverflow.com/questions/17315737/split-a-large-pandas-dataframe
def split_dataframe(df, chunk_size=20, min_size=10):
chunks = list()
remainder = len(df) % chunk_size
if 0 < remainder < min_size:
num_chunks = len(df) // chunk_size - 1
for i in range(num_chunks):
chunks.append(df[i * chunk_size:(i + 1) * chunk_size])
df_ = df[(num_chunks) * chunk_size:]
last_break = int(len(df_) / 2)
chunks.append(df_[:last_break])
chunks.append(df_[last_break:])
return chunks
else:
num_chunks = len(df) // chunk_size + 1
for i in range(num_chunks):
chunks.append(df[i*chunk_size:(i+1)*chunk_size])
return chunks
new_array = []
for group, df_ in df.groupby(df.columns[3], as_index=False):
new_array.extend(split_dataframe(df_))
count_index_ = 0
for count_index in range(len(new_array)):
print("count", count_index, "Size", len(new_array[count_index]))
print(new_array[count_index])
count_index_ += count_index
print(count_index_)
我從一開始就關注這篇文章,對討論將如何進行感到好奇,因為 OP 的問題並不總是可以解決。
舉個例子:一個組有 19 個元素,你想把它分成大小在 10 到 15 之間的部分。
當且僅當存在 integer g 時,解決方案才存在,使得n/b <= g <= n/a
。 在這種情況下,您可以看到長度a
g
部分將使用g*a <= n
元素,長度為b
的部分將使用g*b >= n
。
在這種情況下,也可以有一個平衡分區,最大的部分最多比最小的部分大一個記錄(最小的部分將有n//g
條記錄)。
我們可以對問題進行輕微修改,將其拆分為盡可能少的部分,每個部分最多包含b
條記錄。 使得每個部分的長度滿足a <= len(s) <= a+1
。
請注意,在這種情況下,我們將a
與b
最接近,以便問題有解決方案。 對於可解決的問題,解決方案將是原始問題的解決方案,對於無法解決的問題,它將通過減少a
來修改原始需求,以便問題可以解決。
上面的示例將變為: 在不超過 15 個元素的盡可能少的平衡組中拆分 19 個元素。 然后解決方案是包含 10 個元素的部分和 9 個元素的部分。
def group_and_split(df, b, column):
'''
- df : a datafame
- b : the largest allowed section
- column: the column by which the data must be grouped
'''
# doing it in a pythonic way
return [np.array_split(y, (len(y)+b-1)//b)
for x, y in df.groupby(column, as_index=False)]
您可以檢查它是否為重述的問題提供了解決方案
pd.DataFrame([{
'num-sections': len(g),
'largest-section': max(len(gi) for gi in g),
'smallest-sections':min(len(gi) for gi in g)
} for g in group_and_split(df, 25, 'D')])
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.