R 基于另一个数据框中的列创建新的数据框行

R 基于另一个数据框中的列创建新的数据框行,r,dataframe,R,Dataframe,我有两个数据帧,其中一个的第一列是一个列表(dfa),另一个的第一列包含列表中的项目,但在某些情况下,每行有多个项目(dfb)。 我要做的是遍历并为dfa中的每个项目创建新行,这发生在dfb的第一列中 DFA DF B 渴望的 dfC Index x 1 1 alpha 2 4 alpha 3 3 beta 4 2 beta 5 1 beta 6 4 gamma 7 1 gamma 8 2 gamma 9

我有两个数据帧,其中一个的第一列是一个列表(dfa),另一个的第一列包含列表中的项目,但在某些情况下,每行有多个项目(dfb)。 我要做的是遍历并为dfa中的每个项目创建新行,这发生在dfb的第一列中

DFA

DF B

渴望的

dfC
  Index   x
1  1     alpha
2  4     alpha
3  3     beta
4  2     beta
5  1     beta
6  4     gamma
7  1     gamma
8  2     gamma
9  3     delta
我正在使用的实际数据: DFA

DF B


首先,让我为你的问题提供一个功能性的答案。我怀疑我的答案是否有效,但它是有效的

# construct toy data
dfA <- data.frame(index = 1:4, X = letters[1:4])

dfB <- data.frame(X = letters[1:4])
dfB$list_elements <- list(c(1, 4), c(3, 2, 1), c(4, 1, 2), c(3))

# define function that provides solution

unlist_merge_df <- function(listed_df, reference_df){
    # reference_df assumed to have columns "X" and "index"
    # listed_df assumed to have column "list_elements"
    df_out <- data.frame(index = c(), X = c())
    my_list <- listed_df$list_elements
    for(idx in 1:length(my_list)){
        df_out <- rbind(df_out, 
                        data.frame(index = my_list[[idx]], 
                                   X = listed_df[idx, 'X'])
                        )
    }
    return(df_out)
}

# call the function
dfC <- unlist_merge_df(dfB, dfA)

# show output in human and R-parseable formats
dfC

dput(dfC)


第二,我要说的是,你现在的处境不太理想。如果你能避免,你可能应该。或者根本不使用数据帧,而只使用列表,或者避免完全构造列出的数据帧(如果可以),直接构造所需的输出

首先,让我为您的问题提供一个功能性的答案。我怀疑我的答案是否有效,但它是有效的

# construct toy data
dfA <- data.frame(index = 1:4, X = letters[1:4])

dfB <- data.frame(X = letters[1:4])
dfB$list_elements <- list(c(1, 4), c(3, 2, 1), c(4, 1, 2), c(3))

# define function that provides solution

unlist_merge_df <- function(listed_df, reference_df){
    # reference_df assumed to have columns "X" and "index"
    # listed_df assumed to have column "list_elements"
    df_out <- data.frame(index = c(), X = c())
    my_list <- listed_df$list_elements
    for(idx in 1:length(my_list)){
        df_out <- rbind(df_out, 
                        data.frame(index = my_list[[idx]], 
                                   X = listed_df[idx, 'X'])
                        )
    }
    return(df_out)
}

# call the function
dfC <- unlist_merge_df(dfB, dfA)

# show output in human and R-parseable formats
dfC

dput(dfC)


第二,我要说的是,你现在的处境不太理想。如果你能避免,你可能应该。或者根本不使用数据帧,而只使用列表,或者避免完全构造列出的数据帧(如果可以),直接构造所需的输出

根据Curt的回答,我想我找到了一个更有效的解决方案……假设我正确地解释了你的目标

我的注释代码如下。您应该能够按原样运行它并获得所需的dfC。需要注意的一点是,我假设(基于您的实际数据)分隔符dfB$Index为“\r\n”

#设置假数据

dfA基于Curt的回答,我认为我找到了一个更有效的解决方案……假设我正确地解释了你的目标

我的注释代码如下。您应该能够按原样运行它并获得所需的dfC。需要注意的一点是,我假设(基于您的实际数据)分隔符dfB$Index为“\r\n”

#设置假数据


如果您可以编辑您的问题,将示例数据包含在可解析的R格式中,那么dfAIt将非常有用。例如,
dput(dfA)
dput(dfB)
@CurtF。我添加了我的示例数据,我担心它可能会太混乱,所以我删除了它并添加了虚构的示例。我不确定
DFA
的用途。
DFB
中的葡萄酒中有一堆额外的空格,因此您可以将其细分为逗号
cheesePairing$Wine@rawr-DFA应该用于索引,但您是对的,我不需要它来解决这个特殊问题。感谢您指出这一点,在做任何其他事情之前去掉多余的空白确实帮助很大。如果您可以编辑您的问题,将示例数据包含在可解析的格式中,这将非常有帮助。例如,
dput(dfA)
dput(dfB)
@CurtF。我添加了我的示例数据,我担心它可能会太混乱,所以我删除了它并添加了虚构的示例。我不确定
DFA
的用途。
DFB
中的葡萄酒中有一堆额外的空格,因此您可以将其细分为逗号
cheesePairing$Wine@rawr-DFA应该用于索引,但您是对的,我不需要它来解决这个特殊问题。谢谢你指出这一点,在做任何其他事情之前去掉多余的空白真的很有帮助。谢谢,我知道这不是一个理想的情况。我是通过网络抓取获得数据的,我正试图让它在数据库中可用,但看起来我可能不得不在数据库查询中更加明确一些。谢谢,我知道这不是一个理想的情况。我通过网络抓取获得数据,并试图使其可用于数据库,但看起来我可能不得不对其进行适当的处理,并在数据库查询中更加明确。当我运行此程序时,我得到了一个空白的数据框,但前几步似乎是朝着正确的方向进行的。由于某些原因,刮削产生了大量额外的\r\n,因此到第三步时,分割的数量已完全关闭。我将尝试删除任何空白,看看这是否有帮助。我只是把我的代码复制到一个单独的R会话中,它运行得很好。无论如何,很高兴听到这有点帮助。我认为strsplit()+gsub()函数对于解决这个问题的任何策略都是至关重要的。regexpr()也可能有帮助。还要检查您正在使用的刮片包是否有一些内置功能来处理这些刮片结果。是否有证据表明这实际上更有效?不管怎样,我的回答都很好,而且+1。@arman它运行得很好。一旦我去掉多余的空格,我就无法用Curt提供的代码获得输出,不管我怎么处理它。@CurtF。感谢向上投票,我认为unlist_merge_df()中的主要效率损失来自于将for循环的结果迭代叠加到df_out上。因为df_out随着每次迭代而变大,所以您要分配内存长度(my_list)倍。因此,在for循环之前预先分配df_out使其具有nrows=length(我的_列表)大致相当于我使用lappy的方法(它为您预先分配)。我几乎可以肯定,微基准测试会支持这一点。当我运行它时,我得到了一个空白的数据帧,但前几步似乎朝着正确的方向发展。由于某些原因,刮削产生了大量额外的\r\n,因此到第三步时,分割的数量已完全关闭。我将尝试删除任何空白,看看这是否有帮助。我只是把我的代码复制到一个单独的R会话中,它运行得很好。无论如何,很高兴听到这有点帮助。我认为strsplit()+gsub()函数对于解决这个问题的任何策略都是至关重要的。regexpr()也可能有帮助。还要检查你正在使用的刮片软件包是否有处理这些刮片结果的内置功能。是否有evid
dput(head(allwines))
structure(list(Wine = c("Albariño", "Aligoté", "Amarone", "Arneis", 
"Asti Spumante", "Auslese"), Description = c("Spanish white wine grape that makes crisp, refreshing, and light-bodied wines.", 
"White wine grape grown in Burgundy making medium-bodied, crisp, dry wines with spicy character.", 
"From Italy’s Veneto Region a strong, dry, long- lived red, made from a blend of partially dried red grapes.", 
"A light-bodied dry wine the Piedmont Region of Italy", "From the Piedmont Region of Italy, A semidry sparkling wine produced from the Moscato di Canelli grape in the village of Asti", 
"German white wine from grapes that are very ripe and thus high in sugar"
)), .Names = c("Wine", "Description"), row.names = c(NA, 6L), class = "data.frame")
> dput(head(cheesePairing))
structure(list(Wine = c("Cabernet Sauvignon\r\n                                \r\n                            \r\n                        \r\n                            \r\n                                \r\n                                    Pinot Noir\r\n                                \r\n                            \r\n                        \r\n                            \r\n                                \r\n                                    Sauvignon Blanc\r\n                                \r\n                            \r\n                        \r\n                            \r\n                                \r\n                                    Zinfandel", 
"Chianti\r\n                                \r\n                            \r\n                        \r\n                            \r\n                                \r\n                                    Pinot Noir\r\n                                \r\n                            \r\n                        \r\n                            \r\n                                \r\n                                    Sangiovese", 
"Chardonnay", "Bardolino\r\n                                \r\n                            \r\n                        \r\n                            \r\n                                \r\n                                    Malbec\r\n                                \r\n                            \r\n                        \r\n                            \r\n                                \r\n                                    Riesling\r\n                                \r\n                            \r\n                        \r\n                            \r\n                                \r\n                                    Rioja\r\n                                \r\n                            \r\n                        \r\n                            \r\n                                \r\n                                    Sauvignon Blanc", 
"Tempranillo", "Asti Spumante"), Cheese = c("Abbaye De Belloc Cheese", 
"Ardrahan cheese", "Asadero cheese", "Asiago cheese", "Azeitao", 
"Baby Swiss Cheese"), Suggestions = c("Pair with apples,  sliced pears OR  a sampling of olives and thin sliced salami.  Pass around slices of baguette.", 
"Serve with a substantial wheat cracker and apples or grapes.", 
"Rajas (blistered chile strips) fresh corn tortillas", "Table water crackers, raw nuts (almond, walnuts)", 
"Nutty brown bread, grapes", "Server with dried fruits, whole grain, nutty breads, nuts"
)), .Names = c("Wine", "Cheese", "Suggestions"), row.names = c(NA, 
6L), class = "data.frame")
# construct toy data
dfA <- data.frame(index = 1:4, X = letters[1:4])

dfB <- data.frame(X = letters[1:4])
dfB$list_elements <- list(c(1, 4), c(3, 2, 1), c(4, 1, 2), c(3))

# define function that provides solution

unlist_merge_df <- function(listed_df, reference_df){
    # reference_df assumed to have columns "X" and "index"
    # listed_df assumed to have column "list_elements"
    df_out <- data.frame(index = c(), X = c())
    my_list <- listed_df$list_elements
    for(idx in 1:length(my_list)){
        df_out <- rbind(df_out, 
                        data.frame(index = my_list[[idx]], 
                                   X = listed_df[idx, 'X'])
                        )
    }
    return(df_out)
}

# call the function
dfC <- unlist_merge_df(dfB, dfA)

# show output in human and R-parseable formats
dfC

dput(dfC)
index   X
1   1   a
2   4   a
3   3   b
4   2   b
5   1   b
6   4   c
7   1   c
8   2   c
9   3   d

structure(list(index = c(1, 4, 3, 2, 1, 4, 1, 2, 3), X = structure(c(1L, 
1L, 2L, 2L, 2L, 3L, 3L, 3L, 4L), .Label = c("a", "b", "c", "d"
), class = "factor")), .Names = c("index", "X"), row.names = c(NA, 
9L), class = "data.frame")
# set up fake data
dfA<-data.frame(Index=c('1','2','3','4'), X=c('alpha','beta','gamma','delta'))
dfB<-data.frame(Index=c('1 \r\n 4','3 \r\n 2 \r\n 1','4 \r\n 1 \r\n 2','3'), X=c('alpha','beta','gamma','delta'))

dfA$Index<-as.character(dfA$Index)
dfA$X<-as.character(dfA$X)
dfB$Index<-as.character(dfB$Index)
dfB$X<-as.character(dfB$X)


dfB_index_parsed<-strsplit(x=dfB$Index,"\r\n") # split Index of dfB by delimiter "\r\n" and store in a list
names(dfB_index_parsed)<-dfB$X
dfB_split_num<-lapply(dfB_index_parsed, length) # find the number of splits per row of dfB and store in a list
dfB_split_num_vec<-do.call('c', dfB_split_num) # convert number of splits above from list to vector

g<-do.call('c',dfB_index_parsed) # store all split values in a single vector
g<-gsub(' ','',g) # remove trailing/leading spaces that occur after split
names(g)<-rep(names(dfB_split_num_vec), dfB_split_num_vec ) # associate each split Index from dfB with X from dfB
g<-g[g %in% dfA$Index] # check which dfB$Index are in dfA$Index

dfC<-data.frame(Index=g, X=names(g)) # construct data.frame