【问题标题】:Updating the values of one column in a pandas dataframe based on input proportion根据输入比例更新熊猫数据框中一列的值
【发布时间】:2018-07-19 14:20:44
【问题描述】:

熊猫数据框的某些列没有。唯一值(比如 4)。这些值将在所有行中具有一定的初始比例。我需要改变输入所需比例。假设我有 100 行,列名 city 具有给定比例的值。

Mumbai  30%
Kolkata 40%
Chennai 10%
Delhi   20%

现在我需要更改列中的值,以便获得所需的比例(或数据结构)。

Mumbai  20%
Kolkata 50%
Chennai 20%
Delhi   10%

在执行此操作时 我想确保在将具有城市 Mumbai 的行的值从 25% 更改为 20% 时,我应该保持其中 20% 与以前相同,仅更改其余 5%,即不要清除所有值并根据新比例填充我正在尝试在熊猫数据框中执行此操作。任何帮助表示赞赏。

编辑:假设我的列看起来像这样,有 10 行。

1   Mumbai
2   Mumbai 
3   Mumbai
4   Kolkata
5   Kolkata
6   Kolkata
7   Kolkata
8   Chennai
9   Delhi
10  Delhi

现在我希望它可以改变一些东西,比如上面的改变。

1   Mumbai
2   Mumbai 
3   Kolkata
4   Kolkata
5   Kolkata
6   Kolkata
7   Kolkata
8   Chennai
9   Chennai
10  Delhi

我不是随机的。 Mumbai 的新行是最后一行的子集。

【问题讨论】:

  • 问题不清楚。您是如何决定从孟买移除 5% 并在加尔各答增加 5% 的?输入是什么?
  • @sathyz mumbai 或 kolkata 只是一个例子。由于一些外部原因,我必须改变比例。我知道所需的比例。所以它是一个输入。
  • 你能构造两个输入数据框吗?给定一个 100 行的数据框,您是否聚合数据框以达到您在此处显示的内容。很清楚,如果你给出你遵循的步骤,你期望什么,你尝试了什么等等。
  • @sathyz 看到我做了一些修改。

标签: python pandas dataframe


【解决方案1】:
from collections import Counter 
import pandas as pd

def set_proportion(df, column, new_proportion):
    proportion = (df[column].value_counts() / df.shape[0]).to_dict()
    prop_diff = {key: new_proportion[key] - proportion[key] for key in new_proportion}
    prop_diff_cnt = {key: int(round(value * df.shape[0])) for key, value in prop_diff.items()}
    to_add = {key: diff for key, diff in prop_diff_cnt.items() if diff > 0}
    to_remove = {key: diff for key, diff in prop_diff_cnt.items() if diff < 0}
    to_add = sum(([key] * diff for key, diff in to_add.items()), [])
    to_remove = sum(([key] * -diff for key, diff in to_remove.items()), [])
    # group to counter to do updates to the dataframe in bulk, one update per each *unique* replacement pair
    counter = Counter(list(zip(to_remove, to_add)))
    for (remove, add), count in counter.items():
        df.loc[df[df[column] == remove].iloc[-count:].index, column] = add    

df = pd.DataFrame(["Mumbai"] * 3 + ["Kolkata"] * 4 + ["Chennai"] + ["Delhi"] * 2, columns=['city']) 
print df 
    city
0   Mumbai
1   Mumbai 
2   Mumbai
3   Kolkata
4   Kolkata
5   Kolkata
6   Kolkata
7   Chennai
8   Delhi
9   Delhi    

set_proportion(df, 'city', {'Mumbai': 0.2, 'Kolkata': 0.5, 'Chennai': 0.2, 'Delhi': 0.1})
print df 
      city
0  Mumbai 
1  Mumbai 
2  Chennai
3  Kolkata
4  Kolkata
5  Kolkata
6  Kolkata
7  Chennai
8  Delhi  
9  Kolkata

# set_proportion modifies the original dataframe, so we need to reinitialize it
df = pd.DataFrame(["Mumbai"] * 3 + ["Kolkata"] * 4 + ["Chennai"] + ["Delhi"] * 2, columns=['city']) 

set_proportion(df, 'city', {'Mumbai': 0.2, 'Kolkata': 0.1, 'Chennai': 0.3, 'Delhi': 0.4})
print df 

      city
0  Mumbai 
1  Mumbai 
2  Delhi  
3  Kolkata
4  Delhi  
5  Chennai
6  Chennai
7  Chennai
8  Delhi  
9  Delhi  

【讨论】:

  • 这行得通,谢谢。还有一件事,对于某些列,它们在范围内。即1960-80 :30%需要进行哪些更改?
  • 我认为不需要任何更改。范围列包含字符串,对吧?
猜你喜欢
  • 2017-11-30
  • 1970-01-01
  • 2017-10-14
  • 2023-02-21
  • 1970-01-01
  • 2017-03-11
  • 1970-01-01
  • 2016-08-09
  • 2017-03-23
相关资源
最近更新 更多