Python 基于列的分组和取消分组

Python 基于列的分组和取消分组,python,r,csv,pandas,Python,R,Csv,Pandas,我的目标是能够按列值对CSV文件的行进行分组,并执行反向操作。举例来说,希望能够在这两种格式之间来回转换: uniqueId, groupId, feature_1, feature_2 1, 100, text of 1, 10 2, 100, some text of 2, 20 3, 200, text of 3, 30 4, 200, more text of 4, 40 5, 100, another text of 5, 50 按groupId分组: uniqueId, grou

我的目标是能够按列值对CSV文件的行进行分组,并执行反向操作。举例来说,希望能够在这两种格式之间来回转换:

uniqueId, groupId, feature_1, feature_2
1, 100, text of 1, 10
2, 100, some text of 2, 20
3, 200, text of 3, 30
4, 200, more text of 4, 40
5, 100, another text of 5, 50 
按groupId分组:

uniqueId, groupId, feature_1, feature_2
1|2|5, 100, text of 1|some text of 2|another text of 5, 10|20|50
3|4, 200, text of 3|more text of 4, 30|40
假定分隔符(此处|)不存在于数据中的任何位置

我正在尝试使用熊猫来执行此转换。到目前为止,我的代码可以访问按groupId分组的行单元格,但我不知道如何填充新的dataframe

如何完成我的方法来完成转换为所需的新df

将新df转换回原始df的反向方法会是什么样子

如果R是这份工作的更好工具,我也愿意接受R的建议

import pandas as pd  

def getGroupedDataFrame(df, groupByField, delimiter):
''' Create a df with the rows grouped on groupByField, values separated by delimiter'''
    groupIds = set(df[groupByField])
    df_copy = pd.DataFrame(index=groupIds,columns=df.columns)
    # iterate over the different groupIds
    for groupId in groupIds:
        groupRows = df.loc[df[groupByField] == groupId]
        # for all rows of the groupId
        for index, row in groupRows.iterrows():
            # for all columns in the df
            for column in df.columns:
                print row[column]
                # this prints the value the cell
                # here append row[column] to its cell in the df_copy row of groupId, separated by delimiter

要执行分组,您可以在
'groupId'
上执行
groupby
,然后在每个组内的每个列上使用给定的分隔符执行联接:

def group_delim(grp, delim='|'):
    """Join each columns within a group by the given delimiter."""
    return grp.apply(lambda col: delim.join(col))

# Make sure the DataFrame consists of strings, then apply grouping function.
grouped = df.astype(str).groupby('groupId').apply(group_delim)

# Drop the grouped groupId column, and replace it with the index groupId.
grouped = grouped.drop('groupId', axis=1).reset_index()
分组输出:

  groupId uniqueId                                   feature_1 feature_2
0     100    1|2|5  text of 1|some text of 2|another text of 5  10|20|50
1     200      3|4                    text of 3|more text of 4     30|40 
与反向过程的想法类似,但由于每一行都是一个唯一的组,因此您只需使用常规的
apply
,无需使用
groupby

def ungroup_delim(col, delim='|'):
    """Split elements in a column by the given delimiter, stacking columnwise"""
    return col.str.split(delim, expand=True).stack()

# Apply the ungrouping function, and forward fill elements that aren't grouped.
ungrouped = grouped.apply(ungroup_delim).ffill()

# Drop the unwieldy altered index for a new one.
ungrouped = ungrouped.reset_index(drop=True)
而解组将生成原始数据:

  groupId uniqueId          feature_1 feature_2
0     100        1          text of 1        10
1     100        2     some text of 2        20
2     100        5  another text of 5        50
3     200        3          text of 3        30
4     200        4     more text of 4        40
要使用不同的分隔符,只需将
delim
作为参数传递给
apply

foo.apply(group_delim, delim=';')

作为补充说明,一般来说,在数据帧上迭代相当慢。只要有可能,您就会希望使用像我上面所做的那样的矢量化方法。

要执行分组,您可以在
'groupId'
上执行
groupby
,然后在每个组内的每个列上使用给定的分隔符执行联接:

def group_delim(grp, delim='|'):
    """Join each columns within a group by the given delimiter."""
    return grp.apply(lambda col: delim.join(col))

# Make sure the DataFrame consists of strings, then apply grouping function.
grouped = df.astype(str).groupby('groupId').apply(group_delim)

# Drop the grouped groupId column, and replace it with the index groupId.
grouped = grouped.drop('groupId', axis=1).reset_index()
分组输出:

  groupId uniqueId                                   feature_1 feature_2
0     100    1|2|5  text of 1|some text of 2|another text of 5  10|20|50
1     200      3|4                    text of 3|more text of 4     30|40 
与反向过程的想法类似,但由于每一行都是一个唯一的组,因此您只需使用常规的
apply
,无需使用
groupby

def ungroup_delim(col, delim='|'):
    """Split elements in a column by the given delimiter, stacking columnwise"""
    return col.str.split(delim, expand=True).stack()

# Apply the ungrouping function, and forward fill elements that aren't grouped.
ungrouped = grouped.apply(ungroup_delim).ffill()

# Drop the unwieldy altered index for a new one.
ungrouped = ungrouped.reset_index(drop=True)
而解组将生成原始数据:

  groupId uniqueId          feature_1 feature_2
0     100        1          text of 1        10
1     100        2     some text of 2        20
2     100        5  another text of 5        50
3     200        3          text of 3        30
4     200        4     more text of 4        40
要使用不同的分隔符,只需将
delim
作为参数传递给
apply

foo.apply(group_delim, delim=';')
作为补充说明,一般来说,在数据帧上迭代相当慢。只要有可能,您就会希望使用像我上面所做的那样的矢量化方法。

R中的解决方案:

我定义了初始数据帧(为了清晰起见)

要解组并返回原始数据帧,请执行以下操作:

# Group and summarise using dplyr
library(dplyr)
grouped <- df %>% group_by(groupID) %>% summarise_each(funs(paste(.,collapse = "|")))
library(stringr)
apply(grouped, 1, function(x)  {

        temp <- data.frame(str_split(x, '\\|'), stringsAsFactors = F)
        colnames(temp) <- names(x)
        temp

        }) %>%
        bind_rows()
R中的解决方案:

我定义了初始数据帧(为了清晰起见)

要解组并返回原始数据帧,请执行以下操作:

# Group and summarise using dplyr
library(dplyr)
grouped <- df %>% group_by(groupID) %>% summarise_each(funs(paste(.,collapse = "|")))
library(stringr)
apply(grouped, 1, function(x)  {

        temp <- data.frame(str_split(x, '\\|'), stringsAsFactors = F)
        colnames(temp) <- names(x)
        temp

        }) %>%
        bind_rows()

我注意到,在col.str.split(delim,expand=True)的旧版本中,expand不是一个已知的关键字参数。我注意到,在col.str.split(delim,expand=True)的旧版本中,expand不是一个已知的关键字参数。一个规避这一问题的解决方案是