将列比例转换为1到10的范围

时间:2018-07-25 22:51:06

标签: python pandas numpy

我正在尝试使用函数创建一组新列,这些新列将从数据框中的现有列派生。这是产生错误的示例代码,我想知道是否有比循环更好的更有效的方法

import numpy as np
import pandas as pd

dates = pd.date_range('1/1/2000', periods=100, freq='M')
long_df = pd.DataFrame(np.random.randn(100, 4),index=dates, columns=['Colorado', 'Texas', 'New York', 'Ohio'])
mylist=['Colorado', 'Texas', 'New York', 'Ohio']

def trnsfrm_1_10 (a, b):
    b = (a-np.min(a))/(np.max(a)-np.min(a))*9+1
    return b

for a in mylist:   
    b=a+"_T"
    long_df[b] = long_df.apply(lambda row: trnsfrm_1_10(row[a], row[b]), axis=1)

为澄清上述问题,以下是DataFrame的示例,该示例具有输入列(科罗拉多州,德克萨斯州,纽约)和输出变量(T_Colorado,T_Texas,T_New York)。假设如果对于每个输入变量,下面是每列的最小值和最大值,则通过对每列应用方程式:b =(a-min)/(max-min)* 9 + 1,输出变量为T_Colorado T_Texas T_New约克我只需要基于5行在excel中模拟此过程,但是将最小值和最大值作为函数的一部分进行计算将非常有用,因为我在真实数据中会有很多行。我是Python和Pandas的新手,非常感谢您的帮助。

这些是最小和最大示例

    Colorado    Texas   New York
min   0.03     -1.26    -1.04           
max   1.17      0.37     0.86

这是DataFrame的示例

Index     Colorado  Texas   New York T_Colorado T_Texas  T_New York
1/31/2000   0.03     0.37    0.09      1.00      10.00     6.35
2/29/2000   0.4      0.26   -1.04      3.92       9.39     1.00
3/31/2000   0.35    -0.06   -0.75      3.53       7.63     2.37
4/30/2000   1.17    -1.26   -0.61     10.00       1.00     3.04
5/31/2000   0.46    -0.79    0.86      4.39       3.60     10.00

2 个答案:

答案 0 :(得分:2)

IIUC,您应该利用广播

matrix(unlist(read.table("/Users/Users/Desktop/Test")), 
ncol = 3, byrow = TRUE)-> Matrix

然后long_df2= (long_df - long_df.min())/(long_df.max() - long_df.min()) * 9 + 1

concat

答案 1 :(得分:1)

在您的代码中,错误是当您定义trnsfrm_1_10时,b是一个参数,而实际上只是您的输出。它不应该是参数,尤其是它是您要在循环for期间创建的新列中的值时。因此代码将类似于:

def trnsfrm_1_10 (a):
    b = (a-np.min(a))/(np.max(a)-np.min(a))*9+1
    return b

for a in mylist:   
    b=a+"_T"
    long_df[b] = long_df.apply(lambda row: trnsfrm_1_10(row[a]), axis=1)

另一件事是您在np.min(a)中计算trnsfrm_1_10,实际上等于a(与max相同),因为您apply行对因此a是您所在行和列中的唯一值。我假设您的意思是更多np.min(long_df['a']),也可以写成long_df[a].min()

如果我理解得很清楚,您实际上要执行的操作是:

dates = pd.date_range('1/1/2000', periods=100, freq='M')
long_df = pd.DataFrame(np.random.randn(100, 4),index=dates, 
                       columns=['Colorado', 'Texas', 'New York', 'Ohio'])
mylist=['Colorado', 'Texas', 'New York', 'Ohio']

for a in mylist:
    long_df[a+"_T"] = (long_df[a]-long_df[a].min())/(long_df[a].max()-long_df[a].min())*9+1

然后给予:

long_df.head()
Out[29]: 
            Colorado     Texas  New York      Ohio  Colorado_T   Texas_T  \
2000-01-31 -0.762666  1.413276  0.857333  0.648960    3.192754  7.768111   
2000-02-29  0.148023  0.304971  1.954966  0.656787    4.676018  6.082177   
2000-03-31  0.531195  1.283100  0.070963  1.098968    5.300102  7.570091   
2000-04-30 -0.385679  0.425382  1.330285  0.496238    3.806763  6.265344   
2000-05-31 -0.047057 -0.362419 -2.276546  0.297990    4.358285  5.066955   

            New York_T    Ohio_T  
2000-01-31    6.390972  5.659870  
2000-02-29    8.242445  5.676254  
2000-03-31    5.064533  6.601876  
2000-04-30    7.188740  5.340175  
2000-05-31    1.104787  4.925180  

其中,带有_T的列中的所有值都是从相应列中计算得出的。

最终不要在列上使用for循环,您可以这样做:

long_df_T =(((long_df -long_df.min(axis=0))/(long_df.max(axis=0) -long_df.min(axis=0))*9 +1)
             .add_suffix('_T'))

立即创建一个包含所有带有_T的列的数据框。然后很少有选项可以将它们添加到long_df中,一种方法是使用join

long_df = long_df.join(long_df_T)