首页 > 解决方案 > Pandas 中的数据操作:从列上的值创建一个布尔列,然后用另一列中的值填充

问题描述

好的,我已经尝试这个太久了,是时候寻求帮助了。我有一个看起来有点像这样的数据框:

  person  fruit   quantity    all_fruits
0 p1      grapes  2           [grapes, banana]
1 p1      banana  1           [grapes, banana]
2 p2      apple   4           [apple, banana, peach]
3 p2      banana  4           [apple, banana, peach]
4 p2      peach   2           [apple, banana, peach]
5 p3      grapes  1           [grapes]
6 p4      banana  1           [banana]
7 p5      apple   3           [apple, peach]
8 p5      peach   2           [apple, peach]

然后我有一个“感兴趣的水果”清单:

fruits_of_interest:['苹果','香蕉']

我需要做的是:

  1. 为每个感兴趣的水果创建一个列,并为第 1 列(人)上的每个人指定她是否有该水果

  2. 对于第 1 列中的每个人,分配该人在该水果列下的感兴趣水果数量的 log(1+x)

我正在努力完成这项工作!我的实际数据框非常大,接近 80 万行,而且“感兴趣的水果”列表有 300 多个“水果”,这无济于事。

在第一部分,我使用了这个函数,并且可以获得所有带有布尔值的列来判断是否有水果:

def has_fruit(fruit, row):
        one_string = '\t'.join(row)
        return fruit in one_string
def process_fruits(df, fruits_of_interest):
    for fruit in fruits_of_interest:
        df[fruit] = [has_fruit(fruit, x) for x in df['all_fruits']]
    return df

我需要分配值的第二部分是我根本无法工作的部分!我已经尝试过使用其他功能一次完成所有操作,但它并没有完全做到它应该做的事情:

def process_fruits2(df, fruits_of_interest):
    for fruit in fruits_of_interest:
        if [has_fruit(fruit, x) for x in df['all_fruits']]:
            df[fruit] = np.log1p(df.loc[df['fruit'] == fruit].quantity)

    return df

我做错了什么,我怎么能做到这一点?

添加预期输出:

这将是一个类似这样的数据框(如下面的答案,但只包含来自列表 fruits_of_interest 的水果):

person  apple     banana                                        
p1      0.000000  0.693147
p2      1.609438  1.609438
p3      0.000000  0.000000
p4      0.000000  0.693147
p5      1.386294  0.000000

标签: pythonpandasfunctiondataframedata-wrangling

解决方案


这是一种方法。我创建了一个包含人(行)与水果(列)的数据透视表:

from io import StringIO
import numpy as np
import pandas as pd

# create data frame
data = '''person  fruit   quantity
p1      grapes  2
p1      banana  1
p2      apple   4
p2      banana  4
p2      peach   2
p3      grapes  1
p4      banana  1
p5      apple   3
p5      peach   2
'''
df = pd.read_csv(StringIO(data), sep='\s+', engine='python')

计算数据透视表和日志 (1 + x):

# create summary table: person x fruit
df = df.pivot_table(index='person', columns='fruit', 
                    values='quantity', aggfunc=sum, fill_value=0)

# compute log(1 + fruit)
print(df, end='\n\n')
print(np.log(1 + df))

fruit   apple  banana  grapes  peach
person                              
p1          0       1       2      0
p2          4       4       0      2
p3          0       0       1      0
p4          0       1       0      0
p5          3       0       0      2

fruit      apple    banana    grapes     peach
person                                        
p1      0.000000  0.693147  1.098612  0.000000
p2      1.609438  1.609438  0.000000  1.098612
p3      0.000000  0.000000  0.693147  0.000000
p4      0.000000  0.693147  0.000000  0.000000
p5      1.386294  0.000000  0.000000  1.098612

推荐阅读