【问题标题】:Assign same random value to A-B , B-A pairs in python Dataframe在 python Dataframe 中为 A-B , B-A 对分配相同的随机值
【发布时间】:2018-02-25 00:44:22
【问题描述】:

我有一个类似的数据框

 Sou  Des
  1    3
  1    4
  2    3
  2    4
  3    1
  3    2
  4    1
  4    2

我需要为 0 到 1 之间的每一对分配随机值,但必须为“1-3”、“3-1”和其他对等相似对分配相同的随机值。我期待像

这样的结果数据框
 Sou  Des   Val
  1    3    0.1
  1    4    0.6
  2    3    0.9
  2    4    0.5
  3    1    0.1
  3    2    0.9
  4    1    0.6
  4    2    0.5

如何在 python pandas 中分配相同的随机值相似对,例如“A-B”和“B-A”。

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    让我们首先创建一个按axis=1 helper DF排序的:

    In [304]: x = pd.DataFrame(np.sort(df, axis=1), df.index, df.columns)
    
    In [305]: x
    Out[305]:
       Sou  Des
    0    1    3
    1    1    4
    2    2    3
    3    2    4
    4    1    3
    5    2    3
    6    1    4
    7    2    4
    

    现在我们可以按列分组:

    In [306]: df['Val'] = (x.assign(c=1)
                            .groupby(x.columns.tolist())
                            .transform(lambda x: np.random.rand(1)))
    
    In [307]: df
    Out[307]:
       Sou  Des       Val
    0    1    3  0.989035
    1    1    4  0.918397
    2    2    3  0.463653
    3    2    4  0.313669
    4    3    1  0.989035
    5    3    2  0.463653
    6    4    1  0.918397
    7    4    2  0.313669
    

    【讨论】:

    • 寻找新方法 :-)
    【解决方案2】:

    这是新方法

    s=pd.crosstab(df.Sou,df.Des)
    
    b = np.random.random_integers(-2000,2000,size=(len(s),len(s)))
    sy = (b + b.T)/2
    
    s.mul(sy).replace(0,np.nan).stack().reset_index()
    
    Out[292]: 
       Sou  Des       0
    0    1    3   -60.0
    1    1    4  -867.0
    2    2    3   269.0
    3    2    4  1152.0
    4    3    1   -60.0
    5    3    2   269.0
    6    4    1  -867.0
    7    4    2  1152.0
    

    【讨论】:

      【解决方案3】:

      这里的诀窍是在数据框之外做一些工作。您可以将其分解为三个步骤:

      • 组装所有元组的列表(a,b)
      • 为每一对分配一个随机值,使(a,b)(b,a) 具有相同的值
      • 填写新栏目

      假设您的数据框名为df,我们可以列出所有排序的对,以便a <= b。我认为这比同时跟踪(a,b)(b,a) 更容易。

      pairs = set([(a,b) if a <= b else (b,a) 
                   for a, b in df.itertuples(index=False,name=None))
      

      为这些对中的每一对分配一个随机数并将其存储在字典中很简单,所以我将把它留给你。叫它pair_dict

      现在,我们只需要查找值。我们最终会想写

      df['Val'] = df.apply(<some function>, axis=1)
      

      我们的函数在pair_dict 中查找适当的值。

      与其尝试将它塞进一个 lambda(尽管我们可以),不如让我们单独编写它。

      def func(row):
          if row['Sou'] <= row['Des']:
              key = (row['Sou'], row['Des'])
          else:
              key = (row['Des'], row['Sou'])
          return pair_dict[key]
      

      【讨论】:

        【解决方案4】:

        如果您可以使用来自 hash() 方法的 "random" 值,您可以使用 freezeset() 实现

        df = pd.DataFrame([[1,1,2,2,3,3,4,4],[3,4,3,4,1,2,1,2]]).T
        df.columns = ['Sou','Des']
        df['Val']= df.apply(lambda x: hash(frozenset([x["Sou"],x["Des"]])),axis=1)
        print df
        

        给出:

           Sou  Des         Val
        0    1    3  1580307032
        1    1    4 -1736016661
        2    2    3   741508915
        3    2    4 -1930135584
        4    3    1  1580307032
        5    3    2   741508915
        6    4    1 -1736016661
        7    4    2 -1930135584
        

        参考: Why aren't Python sets hashable?

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-03-29
          • 1970-01-01
          • 2021-10-06
          • 1970-01-01
          • 1970-01-01
          • 2011-12-23
          • 2015-09-14
          • 1970-01-01
          相关资源
          最近更新 更多