根据熊猫中的条件填充数据框列

时间:2020-04-19 11:47:58

标签: python python-3.x pandas python-2.7 dataframe

我有两个数据框,如下所示

main_activity.xml

并且要求是根据df_input中的值填充df_ouput


    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <EditText

            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ems="10"
            android:hint="Enter here"
            android:inputType="textPersonName"
            android:textSize="26sp"
            android:textStyle="bold"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"

            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_bias="0.371" />

        <TextView
            android:id="@+id/textView2"
            android:layout_width="85dp"
            android:layout_height="25dp"
            android:layout_marginTop="88dp"
            android:text="TextView"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.496"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    </androidx.constraintlayout.widget.ConstraintLayout>

因此,基本上,来自df_input的列值将是df_output中匹配并基于df_input.id == df_output.id的单元格值

我正在尝试以下

         df_input                                    df_output
id       POLL_X  POLL_Y  POLL_Z ..     id   Pass_01  Pass_02  Pass_03 .....
110101       1       2       4       110101             
110102       2       1       3       110102

-驱动程序功能---

            df_input                                    df_output
  id   POLL_X  POLL_Y  POLL_Z ....       id   Pass_01  Pass_02  Pass_03 .....
110101     1       2       3            110101     X       Y         Z  
110102     2       1       3            110102     Y       X         Z

number_of_columnsiwthPass是常量,它给出名称为pass的列总数。

我也无法遍历每行,因为这将花费大量时间,必须在基于列或基于lambda的地方进行

两个数据帧中还有其他列,df_input.id == df_output.id也必须匹配

列的总数可以在40左右,一些测试值包括POLL_DNW,POLL_DO,POLL_DOES,POLL_SIG:2
所以我必须在'_'和列号之后加上01,02,03,04 ---- 10,11,-21,--- 39,40

3 个答案:

答案 0 :(得分:1)

我假设一开始您具有正确的列名的 df_output (如填充后的样子)。

要执行任务:

  1. import re(稍后将使用)。

  2. 定义以下函数,根据源行生成输出行:

    def genRow(row):
        ind = []
        vals = []
        for k, v in row.iteritems():
            mtch = re.match('POLL_(.+)', k)
            if mtch:
                ind.append('Pass_' + str(v).zfill(2))
                vals.append(mtch.group(1))
            else:
                ind.append(k)
                vals.append(v)
        return pd.Series(vals, index=ind).rename(row.name)
    

    请注意,此函数用“替换”任何 POLL _... 列 相应的 Pass _... 列,并保留其他列。

  3. 应用它:

    df_output = df_input.apply(genRow, axis=1).reindex(columns=df_output.columns)
    

步骤:

  • df_input.apply(...)-生成“初步”输出DataFrame。 请注意,目前列顺序为字母
  • reindex(...)-使用列名为上述DataFrame重新索引 来自 df_output ,提供正确的列顺序。
  • df_output =-用上述结果覆盖 df_output

编辑

如果您输入的DataFrame在 POLL _... 列中包含重复的值, 需要稍作修改。 这种情况导致输出行中这两个(或更多)元素具有 相同索引,因此如果无法构建整个DataFrame 包括这样的行。

补救措施是使用以下命令将这些元素“压缩”为一个元素: 原始索引,并将所有值转换为包含例如 逗号分隔的原始值列表。

要执行此操作,请将 genRow 函数中的最后一行更改为:

out = pd.Series(vals, index=ind).rename(row.name)
return out.groupby(lambda key: key).apply(lambda lst: (', '.join(sorted(lst))))

答案 1 :(得分:0)

从df_input创建两个数据帧并输出,将它们合并并向后旋转以得到最终的数据帧:

#create first dataframe
    res1 = pd.wide_to_long(df,
                       stubnames='Pass',
                       i='id',
                       j='letters',
                       sep='_',
                       suffix='[A-Z]').reset_index()
                          )
res1

     id letters Pass
0   110101  X   1
1   110102  X   2
2   110101  Y   2
3   110102  Y   1
4   110101  Z   4
5   110102  Z   3

#create second dataframe
res2 = (df1
        .melt('id')
        .drop('value', axis=1)
        .assign(numbers=lambda x: x.variable.str.split('_').str.get(-1))
        .astype( {'numbers': int})
       )

res2

      id    variable    numbers
0   110101  Pass_01       1
1   110102  Pass_01       1
2   110101  Pass_02       2
3   110102  Pass_02       2
4   110101  Pass_03       3
5   110102  Pass_03       3

#merge the two dataframes, and pivot to get ur final output

outcome = (res1
           .merge(res2,
                  left_on=['id','Pass'],
                  right_on=['id','numbers'],
                  how='right')
           .pivot(columns='variable',values='letters',index='id')
           .bfill()
           .reset_index()
           .rename_axis(columns=None)
          )

outcome

      id    Pass_01 Pass_02 Pass_03
0   110101     X       Y       Z
1   110102     Y       X       Z

答案 2 :(得分:0)

您可以使用Do I cast the result of malloc?stack以及一些unstackset_index来处理逻辑中的列。

In [11]: import numpy as np
    ...: import math
    ...: c = []
    ...: angle=np.arange(0.1,10,1)
    ...: for d in angle:
    ...:     r=(d*np.pi)/180
    ...:     c.append(math.cos(r))
    ...:

In [12]: c
Out[12]:
[0.9999984769132877,
 0.9998157121216442,
 0.9993283937786562,
 0.9985366703262117,
 0.997440782930944,
 0.9960410654107695,
 0.9943379441332046,
 0.9923319378854887,
 0.9900236577165575,
 0.9874138067509114]

注意:如果您不想在流程中包括其他列,请首先将它们设置为ID为索引的索引,例如df2 = (df1.set_index('id') #set index any columns not in the logic of pass # remove the prefix Pass_ .rename(columns=lambda col: col.replace('Pass_', '')) # stack the datafrae to make it a serie and sort the passes .stack().sort_values() # next two method exchange the old pass index to the new pass index .reset_index(level=1, name='Pass') .set_index('Pass', append=True)['level_1'] # from the serie to the dataframe shape .unstack() # rename the columns with the prefix pass_ .rename(columns=lambda col: f'Pass_{col:02}') # rename axis to none .rename_axis(None, axis=1) # but back the id as a column .reset_index()) print (df2) id Pass_01 Pass_02 Pass_03 0 110101 X Y Z 1 110102 Y X Z