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