Python 熊猫:反向喜欢调查答案

Python 熊猫:反向喜欢调查答案,python,pandas,Python,Pandas,我有以下问题: 我有一个调查,其中包含了大量关于利克特问题的答案,如: id | Q1 | Q2 | Q3 1 5 3 1 2 3 4 1 3 2 3 1 问题是并非所有问题都是“同一方向”提出的。因此,第一季度的答案为“5”表示答案为肯定。但第二季度的5分意味着一个强烈的否定答案 我们目前正在手工重新编码所有问题(因此将所有Q2 5替换为1等),但我想知道是否有更快的方法来解决这个问题 我想把所有答案除以5,然后再减去1,但这永远不

我有以下问题:

我有一个调查,其中包含了大量关于利克特问题的答案,如:

id | Q1 | Q2 | Q3
1     5    3    1
2     3    4    1
3     2    3    1
问题是并非所有问题都是“同一方向”提出的。因此,第一季度的答案为“5”表示答案为肯定。但第二季度的5分意味着一个强烈的否定答案

我们目前正在手工重新编码所有问题(因此将所有Q2 5替换为1等),但我想知道是否有更快的方法来解决这个问题


我想把所有答案除以5,然后再减去1,但这永远不会给我整数。数学不是我的强项,所以我想知道这里是否有人能帮我解决这个问题

如果我理解正确,你可以这样做:

df['Q2'] = df['Q2'].map({1:5, 2:4, 3:3, 4:2, 5:1})
输入:

   Q1  Q2  Q3
0   5   3   1
1   3   4   1
2   2   5   1
输出:

   Q1  Q2  Q3
0   5   3   1
1   3   2   1
2   2   1   1

我个人会这样做

考虑到您的示例
data.csv

id,q1,q2,q3
1,5,3,1
2,3,4,1
3,2,3,1
我的解决办法是

import pandas as pd

df = pd.read_csv('test_csv.csv')
print df
    id  q1  q2  q3
0   1   5   3   1
1   2   3   4   1
2   3   2   3   1

my_rates = [1, 2, 3, 4, 5]
df['q2'] = df['q2'].apply(lambda x:my_rates[-x])
print df
   id  q1  q2  q3
0   1   5   3   1
1   2   3   2   1
2   3   2   3   1
基准 对于较大的数据集,结果会发生剧烈变化

import pandas as pd
import timeit

df = pd.read_csv('test_csv.csv')
df = pd.concat([df] * 1000, ignore_index=True)

def imcoins(df):
    my_rates = [1, 2, 3, 4, 5]
    df['Q2'] = df['Q2'].apply(lambda x:my_rates[-x])
    return df

def joe(df):
    df['Q2'] = df['Q2'].map({1:5, 2:4, 3:3, 4:2, 5:1})
    return df

def jez(df):
    df.Q2 = 6 - df.Q2
    return df

def jez_2(df):
    df.Q2 = df.Q2.rsub(6)
    return df

def jez_3(df):
    df.Q2 = 6 - df.Q2.values
    return df

nb = 10000
t1 = timeit.timeit(stmt='imcoins(df)', setup='from __main__ import imcoins, df', number=nb)
t2 = timeit.timeit(stmt='joe(df)', setup='from __main__ import joe, df', number=nb)
t3 = timeit.timeit(stmt='jez(df)', setup='from __main__ import jez, df', number=nb)
t4 = timeit.timeit(stmt='jez_2(df)', setup='from __main__ import jez_2, df', number=nb)
t5 = timeit.timeit(stmt='jez_3(df)', setup='from __main__ import jez_3, df', number=nb)

print 'IMCoins : {}\njoe : {}\njezrael_1 : {}\njezrael_2 : {}\tjezrael_3 : {}'.format(t1, t2, t3, t4, t5)

# Python 2.7
IMCoins : 3.85911526513
joe : 1.26151379163
jezrael_1 : 0.487986194544
jezrael_2 : 0.613230951967
jezrael_3 : 0.287318529541

# Python 3.6
IMCoins : 2.0433933256597467
joe : 1.3545644831475654
jezrael_1 : 0.482208606992109
jezrael_2 : 0.5195013265458606
jezrael_3 : 0.27176954323496627

您可以从列
Q2
中减去
6
,或者使用从右侧减去的内容:

print (df)
   Q1  Q2  Q3
0   5   3   1
1   3   4   1
2   2   5   1

df.Q2 = 6 - df.Q2
#same as
#df.Q2 = df.Q2.rsub(6)
如果性能很重要,则减去
numpy数组

df.Q2 = 6 - df.Q2.values
或:

或:




这是一个通用函数,它可以处理数据帧中任意数量的列,您可能需要反转代码。让我们用一些示例数据来尝试一下

import pandas as pd

data1 = {
         'A': [3, 3, 3, 3, 3, 3, 3, 3, 3, 3],
         'B': [9, 2, 3, 2, 4, 0, 2, 7, 2, 8],
         'C': [2, 4, 1, 0, 2, 1, 3, 0, 7, 8]
         }
df1 = pd.DataFrame(data1)
现在,该函数将对A列和B列中的数据进行反向编码

# columns to reverse code
vars = ['A', 'B']

# define function to reverse code data
def reverse_code(data):
    cols = data.columns
    max_value = data.max(axis=0)
    if set(vars) & set(cols):
         data[cols] = (max_value + 1) - data[cols]
    
    return data
    print(cols)
    

print('\nreverse-coded \n', reverse_code(df1))

df1
    A  B  C
0  3  9  2
1  3  2  4
2  3  3  1
3  3  2  0
4  3  4  2
5  3  0  1
6  3  2  3
7  3  7  0
8  3  2  7
9  3  8  8

reverse-coded
    A   B  C
0  1   1  7
1  1   8  5
2  1   7  8
3  1   8  9
4  1   6  7
5  1  10  8
6  1   8  6
7  1   3  9
8  1   8  2
9  1   2  1

预期产出是多少?所有问题都按1到5分制进行提问。1为负,5为正。(理想情况下)但由于错误,Q2编码时1为正,5为负。为什么不直接从6中减去要反转的值?@Jasper,如果有答案解决了您的问题,请接受它以表明您的问题。@IMCoins谢谢!我的是我脑海中出现的第一个解决方案。我喜欢这个答案,因为这种方法可以推广到切换到任何其他评级方案。对于较大的数据,请尝试添加
df=pd.concat([df]*1000,忽略_index=True)
。@jezrael做到了,对于大数据集,结果非常不同。@jezrael如果使用python 2.7,结果也会不同(就像我做的那样),或python 3.6(更新版本)。但是,您的解决方案没有移动,或者移动得很慢。@jezrael我使用df.Q2.values进行了更新,但我邀请您编辑这篇文章,以获取您想要添加的更多注释:)因为spyder中的计时非常简单,所以只需使用
%timeit joe(df)
print (df)
   Q1  Q2  Q3
0   5   3   1
1   3   2   1
2   2   1   1
import pandas as pd

data1 = {
         'A': [3, 3, 3, 3, 3, 3, 3, 3, 3, 3],
         'B': [9, 2, 3, 2, 4, 0, 2, 7, 2, 8],
         'C': [2, 4, 1, 0, 2, 1, 3, 0, 7, 8]
         }
df1 = pd.DataFrame(data1)
# columns to reverse code
vars = ['A', 'B']

# define function to reverse code data
def reverse_code(data):
    cols = data.columns
    max_value = data.max(axis=0)
    if set(vars) & set(cols):
         data[cols] = (max_value + 1) - data[cols]
    
    return data
    print(cols)
    

print('\nreverse-coded \n', reverse_code(df1))

df1
    A  B  C
0  3  9  2
1  3  2  4
2  3  3  1
3  3  2  0
4  3  4  2
5  3  0  1
6  3  2  3
7  3  7  0
8  3  2  7
9  3  8  8

reverse-coded
    A   B  C
0  1   1  7
1  1   8  5
2  1   7  8
3  1   8  9
4  1   6  7
5  1  10  8
6  1   8  6
7  1   3  9
8  1   8  2
9  1   2  1